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

JSON Schema 验证:用于 JSON 结构验证的词汇表
draft-wright-json-schema-validation-01

摘要

JSON Schema (application/schema+json) 有多种用途,其中之一是 JSON 实例验证。本文档指定了 JSON Schema 的词汇表,用于描述 JSON 文档的含义,为处理 JSON 数据的用户界面提供提示,并对有效文档的外观进行断言。

读者注意

此草案的议题列表可在 <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 Schema 可用于要求给定的 JSON 文档(实例)满足一定数量的标准。这些标准是通过使用本规范中描述的关键字来断言的。此外,还定义了一组关键字来帮助交互式用户界面实例生成。

本规范将使用 JSON Schema 核心 [json-schema] 规范中定义的术语。

2. 约定和术语

本文档中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“建议”、“可能”和“可选”应按 RFC 2119 [RFC2119] 中的描述进行解释。

本规范使用术语“容器实例”来指代数组和对象实例。它使用术语“子实例”来指代数组元素或对象成员值。

如果数组值的任何两个元素都不 相等 [json-schema],则称数组值中的元素是唯一的。

3. 互操作性注意事项

3.1. 字符串实例的验证

需要注意的是,空字符 (\u0000) 在 JSON 字符串中是有效的。要验证的实例可能包含具有此字符的字符串值,而不管底层编程语言是否能够处理此类数据。

3.2. 数值实例的验证

JSON 规范允许使用任意精度的数字,JSON Schema 不会添加任何此类边界。这意味着,由 JSON Schema 处理的数值实例可以任意大,或者具有任意长的十进制部分,而不管底层编程语言是否能够处理此类数据。

3.3. 正则表达式

两个验证关键字“pattern”和“patternProperties”使用正则表达式来表达约束。这些正则表达式应根据 ECMA 262 [ecma262] 正则表达式方言有效。

此外,考虑到正则表达式构造支持的高度差异,模式作者应将自己限制在以下正则表达式标记中

最后,实现不得将正则表达式视为锚定,无论是在开头还是结尾。这意味着,例如,模式“es”与“expression”匹配。

4. 一般验证注意事项

4.1. 关键字和实例基本类型

大多数验证关键字只约束特定基本类型内的值。当实例的类型不是关键字目标的类型时,验证成功。

例如,关键字“maxLength”将只限制某些(过长的)字符串的有效性。如果实例是数字、布尔值、null、数组或对象,则该关键字将通过验证。

4.2. 基本类型和子值的验证

两个基本类型,数组和对象,允许使用子值。基本类型的验证被认为与子实例的验证是分开的。

对于数组,基本类型验证包括使用“minItems”和“maxItems”验证长度限制,而“items”和“additionalItems”则确定哪些子模式应用于数组的哪些元素。此外,“uniqueItems”和“contains”会验证整个数组的内容。

对于对象,基本类型验证包括使用“required”、“minProperties”、“maxProperties”、“propertyNames”和字符串数组形式的“dependencies”验证哪些属性以及出现多少个属性,而“properties”、“patternProperties”和“additionalProperties”则确定哪些子模式应用于哪些对象属性值。此外,"dependencies" 的模式形式根据特定属性名称的存在情况验证整个对象。

4.3. 约束和缺失关键字

每个 JSON Schema 验证关键字都会添加约束,实例必须满足这些约束才能成功验证。

缺失的验证关键字永远不会限制验证。在某些情况下,这种不执行任何操作的行为与具有某些值的现有关键字相同,这些值在已知的情况下会进行说明。

4.4. 关键字独立性

验证关键字通常独立运行,不会影响彼此的结果。

为了方便模式作者,存在一些例外

5. 元模式

JSON Schema 验证的当前 URI 为 <https://json-schema.fullstack.org.cn/draft-06/schema#>。

6. 验证关键字

模式中的验证关键字对实例的成功验证施加要求。

6.1. multipleOf

"multipleOf" 的值必须是数字,严格大于 0。

只有当实例的数字除以此关键字的值得到整数时,它才有效。

6.2. maximum

"maximum" 的值必须是数字,表示数值实例的包含上限。

如果实例是数字,则只有当实例小于或正好等于 "maximum" 时,此关键字才有效。

6.3. exclusiveMaximum

"exclusiveMaximum" 的值必须是数字,表示数值实例的排除上限。

如果实例是一个数字,则该实例仅在严格小于(不等于)“exclusiveMaximum”的值时才有效。

6.4. 最小值

“minimum”的值必须是一个数字,表示数值实例的包含上限。

如果实例是一个数字,则此关键字仅在实例大于或等于“minimum”时才有效。

6.5. 独占最小值

“exclusiveMinimum”的值必须是一个数字,表示数值实例的独占上限。

如果实例是一个数字,则该实例仅在严格大于(不等于)“exclusiveMinimum”的值时才有效。

6.6. 最大长度

此关键字的值必须是一个非负整数。

如果字符串实例的长度小于或等于此关键字的值,则该字符串实例对此关键字有效。

字符串实例的长度定义为其字符的数量,如RFC 7159 [RFC7159]中定义。

6.7. 最小长度

此关键字的值必须是一个非负整数。

如果字符串实例的长度大于或等于此关键字的值,则该字符串实例对此关键字有效。

字符串实例的长度定义为其字符的数量,如RFC 7159 [RFC7159]中定义。

省略此关键字与值为 0 的行为相同。

6.8. 模式

此关键字的值必须是一个字符串。此字符串应根据 ECMA 262 正则表达式方言,是一个有效的正则表达式。

如果正则表达式成功匹配实例,则字符串实例被认为有效。请记住:正则表达式不会隐式锚定。

6.9. 项目

“items”的值必须是有效的 JSON Schema 或有效的 JSON Schema 数组。

此关键字确定数组的子实例如何验证,并且不直接验证其自身。

如果“items”是一个模式,则当数组中的所有元素都成功地根据该模式验证时,验证成功。

如果“items”是一个模式数组,则当实例的每个元素都根据相同位置的模式(如果有)验证时,验证成功。

省略此关键字与空模式的行为相同。

6.10. 附加项目

“additionalItems”的值必须是一个有效的 JSON Schema。

此关键字确定数组的子实例如何验证,并且不直接验证其自身。

如果“items”是一个模式数组,则当实例元素中每个大于“items”大小的位置的元素都根据“additionalItems”验证时,验证成功。

否则,“additionalItems”必须被忽略,因为“items”模式(可能是空模式的默认值)将应用于所有元素。

省略此关键字与空模式的行为相同。

6.11. 最大项目

此关键字的值必须是一个非负整数。

如果数组实例的大小小于或等于此关键字的值,则该数组实例对此关键字“maxItems”有效。

6.12. 最小项目

此关键字的值必须是一个非负整数。

如果数组实例的大小大于或等于此关键字的值,则该数组实例对此关键字“minItems”有效。

省略此关键字与值为 0 的行为相同。

6.13. 唯一项目

此关键字的值必须是一个布尔值。

如果此关键字的布尔值为 false,则实例验证成功。如果它的布尔值为 true,则当实例的所有元素都唯一时,该实例验证成功。

省略此关键字与值为 false 的行为相同。

6.14. 包含

此关键字的值必须是一个有效的 JSON Schema。

如果数组实例中的至少一个元素根据给定的模式验证有效,则该数组实例对此关键字“contains”有效。

6.15. 最大属性

此关键字的值必须是一个非负整数。

如果对象实例的属性数量小于或等于此关键字的值,则该对象实例对此关键字“maxProperties”有效。

6.16. 最小属性

此关键字的值必须是一个非负整数。

如果对象实例的属性数量大于或等于此关键字的值,则该对象实例对此关键字“minProperties”有效。

省略此关键字与值为 0 的行为相同。

6.17. 要求

此关键字的值必须是一个数组。此数组的元素(如果有)必须是字符串,并且必须是唯一的。

如果数组中的每个项目都是实例中属性的名称,则对象实例对此关键字有效。

省略此关键字与空数组的行为相同。

6.18. 属性

“properties”的值必须是一个对象。此对象的每个值必须是一个有效的 JSON Schema。

此关键字确定对象的子实例如何验证,并且不直接验证其自身。

如果实例和此关键字的值中都出现名称,并且子实例根据相应的模式验证成功,则验证成功。

省略此关键字与空对象的行为相同。

6.19. 模式属性

“patternProperties”的值必须是一个对象。此对象的每个属性名称应根据 ECMA 262 正则表达式方言,是一个有效的正则表达式。此对象的每个属性值必须是一个有效的 JSON Schema。

此关键字确定对象的子实例如何验证,并且不直接验证其自身。原始实例类型对此关键字的验证始终成功。

如果实例名称与作为此关键字的值中属性名称出现的任何正则表达式匹配,并且子实例根据与匹配的正则表达式相对应的每个模式验证成功,则验证成功。

省略此关键字与空对象的行为相同。

6.20. 附加属性

“additionalProperties”的值必须是一个有效的 JSON Schema。

此关键字确定对象的子实例如何验证,并且不直接验证其自身。

使用“additionalProperties”进行的验证仅适用于不匹配“properties”中任何名称的实例名称的子值,也不匹配“patternProperties”中的任何正则表达式。

对于所有此类属性,如果子实例根据“additionalProperties”模式验证成功,则验证成功。

省略此关键字与空模式的行为相同。

6.21. 依赖项

此关键字指定如果实例是一个对象并包含特定属性,则要评估的规则。

此关键字的值必须是一个对象。每个属性指定一个依赖项。每个依赖项值必须是一个数组或有效的 JSON Schema。

如果依赖项值是一个子模式,并且依赖项键是实例中的属性,则整个实例必须根据依赖项值进行验证。

如果依赖项值是一个数组,则数组中的每个元素(如果有)必须是一个字符串,并且必须是唯一的。如果依赖项键是实例中的属性,则依赖项值中的每个项目都必须是存在于实例中的属性。

省略此关键字与空对象的行为相同。

6.22. 属性名称

“propertyNames”的值必须是一个有效的 JSON Schema。

如果实例是一个对象,则此关键字验证实例中的每个属性名称是否根据提供的模式进行验证。请注意,模式要测试的属性名称始终是一个字符串。

省略此关键字与空模式的行为相同。

6.23. 枚举

此关键字的值必须是一个数组。此数组应至少包含一个元素。数组中的元素应是唯一的。

如果实例的值等于此关键字的数组值中的一个元素,则该实例对此关键字验证成功。

数组中的元素可能是任何值,包括 null。

6.24. 常量

此关键字的值可能是任何类型,包括 null。

如果实例的值等于关键字的值,则该实例对此关键字验证成功。

6.25. 类型

此关键字的值必须是一个字符串或一个数组。如果它是一个数组,则数组的元素必须是字符串,并且必须是唯一的。

字符串值必须是六种基本类型之一(“null”、“boolean”、“object”、“array”、“number”或“string”),或“integer”,它匹配任何具有零小数部分的数字。

当且仅当实例位于此关键字列出的任何集合中时,实例才验证成功。

6.26. 所有

此关键字的值必须是一个非空数组。数组的每个项目必须是一个有效的 JSON Schema。

如果实例根据此关键字的值定义的所有模式成功验证,则该实例对此关键字验证成功。

6.27. 任何

此关键字的值必须是一个非空数组。数组的每个项目必须是一个有效的 JSON Schema。

如果实例根据此关键字的值定义的至少一个模式成功验证,则该实例对此关键字验证成功。

6.28. 一个

此关键字的值必须是一个非空数组。数组的每个项目必须是一个有效的 JSON Schema。

如果实例根据此关键字的值定义的正好一个模式成功验证,则该实例对此关键字验证成功。

6.29.

此关键字的值必须是一个有效的 JSON Schema。

如果实例未能根据此关键字定义的模式成功验证,则该实例对此关键字有效。

7. 元数据关键字

7.1. 定义

此关键字的值必须是一个对象。此对象的每个成员值必须是一个有效的 JSON Schema。

此关键字本身在验证中不发挥任何作用。它的作用是为模式作者提供一个标准化位置,以便将 JSON Schema 内联到更通用的模式中。

{
    "type": "array",
    "items": { "$ref": "#/definitions/positiveInteger" },
    "definitions": {
        "positiveInteger": {
            "type": "integer",
            "exclusiveMinimum": 0
        }
    }
}

                        

例如,以下是一个描述正整数数组的模式,其中正整数约束是“definitions”中的子模式

7.2. “title” 和“description”

这两个关键字的值必须是一个字符串。

这两个关键字都可以用来用有关此用户界面生成的数据的信息来装饰用户界面。标题最好简短,而描述将提供有关此模式描述的实例用途的说明。

7.3. “default”

对此关键字的值没有限制。

此关键字可用于提供与特定模式关联的默认 JSON 值。建议默认值根据关联的模式有效。

7.4. “examples”

此关键字的值必须是一个数组。对数组中的值没有限制。

此关键字可用于提供与特定模式关联的示例 JSON 值,以说明用法。建议这些值根据关联的模式有效。

实现可以将“default”的值(如果存在)用作额外的示例。如果“examples”不存在,则“default”仍然可以以这种方式使用。

8. 使用“format”进行语义验证

8.1. 前言

仅结构化验证可能不足以验证实例是否满足应用程序的所有要求。定义了“format”关键字以允许对由权威资源准确描述的值的固定子集进行可互操作的语义验证,无论是 RFC 还是其他外部规范。

此关键字的值称为格式属性。它必须是一个字符串。格式属性通常只能验证给定的一组实例类型。如果要验证的实例的类型不在此集合中,则对此格式属性和实例的验证应成功。

8.2. 实现要求

实现可以支持“format”关键字。如果它们选择这样做

实现 MAY 添加自定义格式属性。为了各方之间的协议一致性,模式作者 SHALL NOT 预期对等实现会支持此关键字和/或自定义格式属性。

8.3. 定义的格式

8.3.1. date-time

此属性适用于字符串实例。

如果字符串实例是 RFC 3339,第 5.6 节 [RFC3339] 中定义的有效日期表示,则它相对于此属性有效。

8.3.2. email

此属性适用于字符串实例。

如果字符串实例是 RFC 5322,第 3.4.1 节 [RFC5322] 中定义的有效 Internet 电子邮件地址,则它相对于此属性有效。

8.3.3. hostname

此属性适用于字符串实例。

如果字符串实例是 RFC 1034,第 3.1 节 [RFC1034] 中定义的有效 Internet 主机名表示,则它相对于此属性有效。

8.3.4. ipv4

此属性适用于字符串实例。

如果字符串实例是根据 RFC 2673,第 3.2 节 [RFC2673] 中定义的 "dotted-quad" ABNF 语法表示的有效 IPv4 地址,则它相对于此属性有效。

8.3.5. ipv6

此属性适用于字符串实例。

如果字符串实例是 RFC 2373,第 2.2 节 [RFC2373] 中定义的有效 IPv6 地址表示,则它相对于此属性有效。

8.3.6. uri

此属性适用于字符串实例。

如果字符串实例是根据 [RFC3986] 定义的有效 URI,则它相对于此属性有效。

8.3.7. uri-reference

此属性适用于字符串实例。

如果字符串实例是根据 [RFC3986] 定义的有效 URI 引用(URI 或相对引用),则它相对于此属性有效。

8.3.8. uri-template

此属性适用于字符串实例。

如果字符串实例是根据 [RFC6570] 定义的有效 URI 模板(任何级别),则它相对于此属性有效。

8.3.9. json-pointer

此属性适用于字符串实例。

如果字符串实例是根据 [RFC6901] 定义的有效 JSON 指针,则它相对于此属性有效。

9. 安全考虑

JSON Schema 验证定义了 JSON Schema 核心词汇表,并涉及其中列出的所有安全考虑。

JSON Schema 验证允许使用正则表达式,而正则表达式有许多不同的(通常是不兼容的)实现。某些实现允许嵌入任意代码,这超出了 JSON Schema 的范围,MUST NOT 被允许。正则表达式通常也可以被设计为计算起来非常昂贵(使用所谓的 "灾难性回溯"),从而导致拒绝服务攻击。

10. 参考文献

10.1. 规范性引用

, "
[RFC2119] Bradner, S.RFC 中使用的指示要求级别的关键词,BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。
[json-schema]JSON Schema:描述 JSON 文档的媒体类型,Internet-Draft draft-wright-json-schema-00,2016 年 10 月。

10.2. 说明性引用

, "
[RFC1034] Mockapetris, P.,"域名 - 概念和设施",STD 13,RFC 1034,DOI 10.17487/RFC1034,1987 年 11 月。
[RFC2373] Hinden, R.S. Deering,"IP 版本 6 地址体系结构",RFC 2373,DOI 10.17487/RFC2373,1998 年 7 月。
[RFC2673] Crawford, M.,"域名系统中的二进制标签",RFC 2673,DOI 10.17487/RFC2673,1999 年 8 月。
[RFC3339] Klyne, G.C. Newman,"互联网上的日期和时间:时间戳",RFC 3339,DOI 10.17487/RFC3339,2002 年 7 月。
[RFC3986] Berners-Lee, T.Fielding, R.L. Masinter,"统一资源标识符 (URI):通用语法",STD 66,RFC 3986,DOI 10.17487/RFC3986,2005 年 1 月。
[RFC6570] Gregorio, J.Fielding, R.Hadley, M.Nottingham, M.D. Orchard,"URI 模板",RFC 6570,DOI 10.17487/RFC6570,2012 年 3 月。
[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 月。
[RFC5322] Resnick, P.互联网邮件格式",RFC 5322,DOI 10.17487/RFC5322,2008 年 10 月。
[ecma262]ECMA 262 规范"

附录 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. 变更日志

[CREF1]离开 Internet-Draft 状态之前应删除此部分。

draft-wright-json-schema-validation-01

draft-wright-json-schema-validation-00

draft-fge-json-schema-validation-01

作者地址

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