互联网工程任务组 A. Wright,编
互联网草案
预期状态:信息 H. Andrews,编
过期时间:2017 年 10 月 23 日 Cloudflare, Inc.
2017 年 4 月 21 日

JSON 模式:用于描述 JSON 文档的媒体类型
draft-wright-json-schema-01

摘要

JSON 模式定义了媒体类型“application/schema+json”,这是一种基于 JSON 的格式,用于描述 JSON 数据的结构。JSON 模式断言 JSON 文档必须是什么样子,提取信息的方法,以及如何与之交互,非常适合为现有的 JSON API 添加注释,这些 API 否则不会有超媒体控制或可机器读取。

致读者

此草案的问题列表可以在 <https://github.com/json-schema-org/json-schema-spec/issues> 找到。

有关更多信息,请参见 <https://json-schema.fullstack.org.cn/>

要提供反馈,请使用此问题跟踪器、主页上列出的通信方法,或向文档编辑人员发送电子邮件。

本备忘录的状态

此互联网草案完全符合 BCP 78 和 BCP 79 的规定。

互联网草案是互联网工程任务组 (IETF) 的工作文档。请注意,其他团体也可能将工作文档作为互联网草案发布。当前互联网草案的列表在 http://datatracker.ietf.org/drafts/current/。

互联网草案是有效期最长为六个月的草案文档,可以随时更新、替换或被其他文档废弃。互联网草案不适合用作参考材料,也不适合引用,除非“正在进行中”。

此互联网草案将于 2017 年 10 月 23 日过期。

版权声明

版权所有 (c) 2017 IETF 信托和被识别为文档作者的人员。保留所有权利。

本文件受 BCP 78 和 IETF 信托的《与 IETF 文档相关的法律条款》(http://trustee.ietf.org/license-info)约束,这些条款在本文件发布之日生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文件摘录的代码组件必须包含简化的 BSD 许可证文本,如信托法律条款第 4.e 节所述,并且按简化的 BSD 许可证中所述提供,不提供任何担保。


目录

1. 引言

JSON 模式是一种 JSON 媒体类型,用于定义 JSON 数据的结构。JSON 模式旨在定义 JSON 数据的验证、文档、超链接导航和交互控制。

本规范定义了 JSON 模式核心术语和机制,包括通过引用指向另一个 JSON 模式、反引用 JSON 模式引用以及指定正在使用的词汇表。

其他规范定义了对验证、链接、注释、导航和交互进行断言的词汇表。

2. 约定和术语

本文件中的关键词“必须”、“禁止”、“必需”、“应”、“不应”、“建议”、“不建议”、“推荐”、“可以”和“可选”应按 RFC 2119 [RFC2119] 中的描述进行解释。

本文件中的术语“JSON”、“JSON 文本”、“JSON 值”、“成员”、“元素”、“对象”、“数组”、“数字”、“字符串”、“布尔值”、“真”、“假”和“空”应按 RFC 7159 [RFC7159] 中的定义进行解释。

3. 概述

本文件提出了一种新的媒体类型“application/schema+json”,用于识别用于描述 JSON 数据的 JSON 模式。JSON 模式本身就是 JSON 文档。本规范及其相关规范定义了关键字,允许作者以多种方式描述 JSON 数据。

3.1. 验证

JSON 模式描述了 JSON 文档的结构(例如,必需属性和长度限制)。应用程序可以使用此信息来验证实例(检查是否满足约束),或告知接口收集用户输入以满足约束。

验证行为和关键字在 单独的文档 [json-schema-validation] 中指定。

3.2. 超媒体和链接

JSON 超模式描述了 JSON 文档的超文本结构。这包括从实例到其他资源的链接关系、对实例作为多媒体数据的解释以及使用 API 所需的提交数据。

超模式行为和关键字在 单独的文档 [json-hyper-schema] 中指定。

4. 定义

4.1. JSON 文档

JSON 文档是由 application/json 媒体类型描述的信息资源(一系列字节)。

在 JSON 模式中,术语“JSON 文档”、“JSON 文本”和“JSON 值”由于其定义的数据模型而可以互换。

JSON 模式仅针对 JSON 文档定义。但是,任何可以解析为 JSON 模式数据模型或根据 JSON 模式数据模型进行处理的文档或内存结构都可以针对 JSON 模式进行解释,包括 CBOR [RFC7049] 等媒体类型。

4.2. 实例

JSON 模式根据数据模型解释文档。根据此数据模型解释的 JSON 值称为“实例”。

实例具有六种基本类型之一,并且根据类型具有各种可能的值

JSON“空”产生式
布尔值
一个“真”或“假”值,来自 JSON“真”或“假”产生式
对象
一组无序的属性,将字符串映射到实例,来自 JSON“对象”产生式
数组
实例的有序列表,来自 JSON“数组”产生式
数字
一个任意精度的基数 10 十进制数,来自 JSON“数字”产生式
字符串
Unicode 代码点的字符串,来自 JSON“字符串”产生式

因此,空格和格式问题超出了 JSON 模式的范围。

由于对象不能有两个具有相同键的属性,因此对于尝试在一个对象中定义两个具有相同键(“字符串”产生式)的属性(“成员”产生式)的 JSON 文档的行为是未定义的。

4.3. 实例相等

当且仅当两个 JSON 实例是相同类型并且根据数据模型具有相同的值时,它们被认为是相等的。具体而言,这意味着

此定义隐含了数组必须具有相同的长度、对象必须具有相同数量的成员、对象中的属性是无序的、没有定义多个具有相同键的属性的方法,并且仅仅的格式差异(缩进、逗号的位置、尾随零)无关紧要。

4.4. JSON 模式文档

JSON 模式文档,或简称为模式,是一个 JSON 文档,用于描述实例。模式本身被解释为实例。JSON 模式必须是一个对象或一个布尔值。

布尔值等效于以下行为

始终通过验证,就像空模式 {} 一样
始终验证失败,就像模式 { "not":{} } 一样

用于描述实例的属性称为关键字或模式关键字。属性的含义由模式使用的词汇表指定。

JSON 模式可以包含不是模式关键字的属性。未知关键字应被忽略。

自身描述模式的模式称为元模式。元模式用于验证 JSON 模式并指定它使用的词汇表。

空模式是一个没有属性或只有未知属性的 JSON 模式。

4.5. 根模式和子模式

根模式是构成所讨论的整个 JSON 文档的模式。

一些关键字本身采用模式,允许 JSON 模式嵌套

{
    "title": "root",
    "items": {
        "title": "array item"
    }
}

                    

在本示例文档中,标题为“数组项目”的模式是一个子模式,标题为“根”的模式是根模式。

与根模式一样,子模式也是一个对象或一个布尔值。

5. 片段标识符

根据 [RFC6839] 的第 3.1 节,为任何 +json 媒体类型指定的片段标识符的语法和语义应与为“application/json”指定的语法和语义相同。(在本文件发布时,尚未为“application/json”定义片段标识语法。)

此外,“application/schema+json”媒体类型支持两种片段标识符结构:普通名称和 JSON 指针。JSON 指针用作 URI 片段标识符的使用在 RFC 6901 [RFC6901] 中描述。与 JSON 指针语法匹配的片段标识符(包括空字符串)必须解释为 JSON 指针片段标识符。

根据 W3C 的 片段标识符最佳实践 [W3C.WD-fragid-best-practices-20121025],普通名称片段标识符保留用于引用本地命名的模式。所有与 JSON 指针语法不匹配的片段标识符必须解释为普通名称片段标识符。

"$id" 关键字 [id-keyword] 部分定义和引用普通名称片段标识符。

6. 一般注意事项

6.1. JSON 值的范围

实例可以是 JSON [RFC7159] 中定义的任何有效 JSON 值。JSON 模式对类型没有任何限制:JSON 模式可以描述任何 JSON 值,包括例如 null。

6.2. 编程语言独立性

JSON Schema 与编程语言无关,支持数据模型中描述的全部值范围。但是请注意,某些语言和 JSON 解析器可能无法在内存中表示 JSON 可描述的全部值范围。

6.3. 数学整数

一些编程语言和解析器使用不同的内部表示来表示浮点数和整数。

为了保持一致性,整数 JSON 数字不应以小数部分编码。

6.4. 扩展 JSON Schema

实现可以为 JSON Schema 定义额外的关键字。除了明确的协议之外,模式作者不应期望这些额外的关键字得到同行实现的支持。实现应该忽略它们不支持的关键字。

鼓励 JSON Schema 扩展的作者编写他们自己的元模式,这些模式使用 "allOf" 扩展现有的元模式。此扩展的元模式应使用 "$schema" 关键字引用,以允许工具遵循正确的行为。

7. "$schema" 关键字

"$schema" 关键字既用作 JSON Schema 版本标识符,也用作资源的位置,该资源本身是一个 JSON Schema,它描述了为该特定版本编写的任何模式。

此关键字的值必须是 URI [RFC3986](包含方案),并且此 URI 必须规范化。当前模式必须针对此 URI 标识的元模式有效。

"$schema" 关键字应在根模式中使用。它不能出现在子模式中。

[CREF1]虽然这种模式可能仍然是模式编写的最佳实践,但实现行为可能会在未来的草案中被修改或放宽。

此属性的值在其他文档和由其他方定义。JSON Schema 实现应根据合理的判断,实现对当前和以前发布的 JSON Schema 词汇表草案的支持。

8. 使用 $ref 的模式引用

"$ref" 关键字用于引用模式,并提供通过自引用验证递归结构的能力。

具有 "$ref" 属性的对象模式必须解释为 "$ref" 引用。"$ref" 属性的值必须是 URI 引用。相对于当前 URI 基准解析,它标识要使用的模式的 URI。"$ref" 对象中的所有其他属性必须被忽略。

URI 不是网络定位器,而只是一个标识符。如果它是可网络寻址的 URL,则模式不必从地址下载,并且实现不应假设它们应该在遇到可网络寻址的 URI 时执行网络操作。

模式不得针对模式陷入无限循环。例如,如果两个模式 "#alice" 和 "#bob" 都有一个 "allOf" 属性,该属性引用另一个属性,则一个简单的验证器可能会陷入无限递归循环中,试图验证实例。模式不应使用这种无限递归嵌套;行为未定义。

9. 基准 URI 和反引用

9.1. 初始基准 URI

RFC3986 第 5.1 节 [RFC3986] 定义了如何确定文档的默认基准 URI。

信息性地,模式的初始基准 URI 是找到它的 URI,或者如果不知道的话,一个合适的替代 URI。

9.2. "$id" 关键字

"$id" 关键字定义了模式的 URI,以及模式中其他 URI 引用解析的基准 URI。"$id" 关键字本身解析为对象整体出现的基准 URI。

如果存在,此关键字的值必须是字符串,并且必须表示有效的 URI 引用 [RFC3986]。此值应规范化,并且不应是空片段 <#> 或空字符串 <>。

JSON Schema 文档的根模式应包含一个带有 URI(包含方案)的 "$id" 关键字。此 URI 应不包含片段,或者包含一个空字符串。 [CREF2]包含具有其他组件的片段的 "$id" URI 引用应如何解释?有两种情况:当其他组件与当前基准 URI 匹配时,以及当它们更改基准 URI 时。

为了在 JSON Schema 文档中命名子模式,子模式可以使用 "$id" 为自己提供一个文档局部标识符。这是通过将 "$id" 设置为仅包含片段的 URI 引用来完成的。片段标识符必须以字母 ([A-Za-z]) 开头,后跟任意数量的字母、数字 ([0-9])、连字符 ("-")、下划线 ("_")、冒号 (":") 或句点 (".")。

定义一个既不符合上述要求也不属于有效 JSON 指针的 "$id" 的效果未定义。

{
    "$id": "http://example.com/root.json",
    "definitions": {
        "A": { "$id": "#foo" },
        "B": {
            "$id": "other.json",
            "definitions": {
                "X": { "$id": "#bar" },
                "Y": { "$id": "t/inner.json" }
            }
        },
        "C": {
            "$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"
        }
    }
}

                        

例如

以下 URI 编码 JSON 指针 [RFC6901](相对于根模式)处的模式具有以下基准 URI,并且根据第 5 节可以由任一 URI 识别

#(文档根)
http://example.com/root.json#
#/definitions/A
http://example.com/root.json#foo
#/definitions/B
http://example.com/other.json
#/definitions/B/definitions/X
http://example.com/other.json#bar
#/definitions/B/definitions/Y
http://example.com/t/inner.json
#/definitions/C
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f

9.2.1. 内部引用

模式可以通过任何赋予它们的 URI 来识别,包括 JSON 指针或它们由 "$id" 直接给出的 URI。

工具应注意模式(包括子模式)使用 "$id" 为自己提供的 URI。这被称为 "内部引用"。

例如,考虑此模式

{
    "$id": "http://example.net/root.json",
    "items": {
        "type": "array",
        "items": { "$ref": "#item" }
    },
    "definitions": {
        "single": {
            "$id": "#item",
            "type": "integer"
        }
    }
}

                        

当实现遇到 <#/definitions/single> 模式时,它将 "$id" URI 引用相对于当前基准 URI 解析,形成 <http://example.net/root.json#item>。

当实现随后查看 <#/items> 模式内部时,它会遇到 <#item> 引用,并将此解析为 <http://example.net/root.json#item>,它被理解为在同一文档中的其他位置定义的模式。

9.2.2. 外部引用

为了在一个庞大的生态系统中区分模式,模式通过 URI 来识别。如上所述,这并不一定意味着会下载任何内容,而是 JSON Schema 实现应该已经了解它们将使用的模式,包括识别它们的 URI。

实现应该能够将任意 URI 与任意模式关联起来,或者根据验证器对模式的信任程度自动关联模式的 "$id" 给出的 URI。

模式可以(并且很可能)具有多个 URI,但 URI 无法识别多个模式。当多个模式尝试使用相同的 URI 标识时,验证器应该引发错误条件。

10. 超媒体的使用

JSON 已被 HTTP 服务器广泛用于自动化 API 和机器人。本节描述了在与支持媒体类型和 Web 链接 [RFC5988] 的协议一起使用时,如何以更 RESTful 的方式增强对 JSON 文档的处理。

10.1. 链接到模式

建议由模式/配置文件描述的实例使用 "describedby" 链接关系提供指向可下载 JSON Schema 的链接,如 链接数据协议 1.0,第 8.1 节 [W3C.REC-ldp-20150226] 中定义的那样。

在 HTTP 中,此类链接可以使用 Link 标头 [RFC5988] 附加到任何响应。此类标头的示例将是

Link: <http://example.com/my-hyper-schema#>; rel="describedby"

                    

10.2. 描述 JSON 的配置文件

实例可以指定 'profile' 链接关系 [RFC6906] 中描述的 "profile"。当用作媒体类型参数时,HTTP 服务器获得基于配置文件执行内容类型协商的能力。媒体类型参数必须是空格分隔的 URI 列表(即,相对引用无效)。

配置文件 URI 是不透明的,不应自动反引用。如果实现不了解提供的配置文件的语义,则实现可以改为遵循 "describedby" 链接(如果有),这些链接可能提供有关如何处理配置文件的信息。由于 "profile" 不一定指向网络位置,因此 "describedby" 关系用于链接到可下载的模式。但是,为了简便起见,模式作者应尽可能使这些 URI 指向同一个资源。

在 HTTP 中,媒体类型参数将在 Content-Type 标头内发送

Content-Type: application/json;
          profile="http://example.com/my-hyper-schema#"

                    

多个配置文件用空格分隔

Content-Type: application/json;
          profile="http://example.com/alice http://example.com/bob"

                    

HTTP 也可以在 Link 中发送 "profile",但如果这完全取代了媒体类型参数,可能会影响媒体类型语义和内容类型协商

Link: </alice>;rel="profile", </bob>;rel="profile"

                    

10.3. 通过 HTTP 的使用

当用于通过网络的超媒体系统时,HTTP [RFC7231] 通常是分发模式的首选协议。如果恶意客户端比必要时更频繁地通过网络提取模式,而实际上可以将模式缓存很长时间,则行为不端的客户端可能会给服务器维护者带来问题。

HTTP 服务器应在 JSON Schema 上设置长时间缓存的标头。HTTP 客户端应观察缓存标头,并且不应在它们的有效期内重新请求文档。分布式系统应利用共享缓存和/或缓存代理。

User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0

                        

客户端应设置或附加特定于 JSON Schema 实现或软件产品的 User-Agent 标头。由于符号按重要性降序排列,因此 JSON Schema 库名称/版本应位于更通用的 HTTP 库名称(如果有)之前。例如

客户端应该能够使用 "From" 标头发出请求,以便服务器操作员可以联系可能行为不端的脚本的所有者。

11. 安全注意事项

模式和实例都是 JSON 值。因此,RFC 7159 [RFC7159] 中定义的所有安全注意事项都适用。

实例和模式通常由不受信任的第三方编写,以部署在公共互联网服务器上。验证器应该注意,解析模式不会消耗过多的系统资源。验证器不得陷入无限循环。

服务器需要注意,恶意方不能通过上传具有预先存在的或非常相似的 "$id" 的模式来更改现有模式的功能。

各个 JSON Schema 词汇表也可能具有它们自己的安全注意事项。请参阅相应的规范以获取更多信息。

12. IANA 注意事项

JSON Schema 的建议 MIME 媒体类型定义如下

13. 参考文献

13.1. 规范性参考文献

[RFC2119] Bradner, S.,"RFC 中用于指示要求级别的关键词",BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。
[RFC3986] Berners-Lee, T.Fielding, R.L. Masinter,"统一资源标识符 (URI):通用语法",STD 66,RFC 3986,DOI 10.17487/RFC3986,2005 年 1 月。
[RFC6839] Hansen, T.A. Melnikov,"附加媒体类型结构化语法后缀",RFC 6839,DOI 10.17487/RFC6839,2013 年 1 月。
[RFC6901] Bryan, P.Zyp, K.M. Nottingham,"JavaScript 对象符号 (JSON) 指针",RFC 6901,DOI 10.17487/RFC6901,2013 年 4 月。
[RFC7159] Bray, T.,"JavaScript 对象符号 (JSON) 数据交换格式",RFC 7159,DOI 10.17487/RFC7159,2014 年 3 月。
[W3C.REC-ldp-20150226] Speicher, S.Arwe, J.A. Malhotra,"链接数据平台 1.0",万维网联盟推荐 REC-ldp-20150226,2015 年 2 月。

13.2. 信息性参考文献

[RFC5988] Nottingham, M.,"网络链接",RFC 5988,DOI 10.17487/RFC5988,2010 年 10 月。
[RFC6906] Wilde, E.,"'profile' 链接关系类型",RFC 6906,DOI 10.17487/RFC6906,2013 年 3 月。
[RFC7049] Bormann, C.P. Hoffman,"简洁二进制对象表示 (CBOR)",RFC 7049,DOI 10.17487/RFC7049,2013 年 10 月。
[RFC7231] Fielding, R.J. Reschke,"超文本传输协议 (HTTP/1.1):语义和内容",RFC 7231,DOI 10.17487/RFC7231,2014 年 6 月。
[W3C.WD-fragid-best-practices-20121025] Tennison, J.,"片段标识符和媒体类型定义的最佳实践",万维网联盟 LastCall WD-fragid-best-practices-20121025,2012 年 10 月。
[json-schema-validation] Wright, A.G. Luff,"JSON 架构验证:JSON 结构验证词汇",互联网草案 draft-wright-json-schema-validation-00,2016 年 10 月。
[json-hyper-schema] Wright, A.G. Luff,"JSON 超级架构:JSON 超媒体注释词汇",互联网草案 draft-wright-json-schema-hyperschema-00,2016 年 10 月。

附录 A. 致谢

感谢 Gary Court、Francis Galiegue、Kris Zyp 和 Geraint Luff 对 JSON Schema 初稿的贡献。

感谢 Jason Desrosiers、Daniel Perrett、Erik Wilde、Ben Hutton、Evgeny Poberezkin、Brad Bowman、Gowry Sankar、Donald Pipowitch 和 Dave Finlay 对本文档的提交和补丁。

附录 B. 变更日志

[CREF3]此部分将在离开互联网草案状态之前删除。

draft-wright-json-schema-01

draft-wright-json-schema-00

draft-zyp-json-schema-04

draft-zyp-json-schema-00

作者地址

Austin Wright(编辑) 电子邮件:[email protected]
Henry Andrews(编辑) Cloudflare, Inc. 电子邮件:[email protected]