互联网工程任务组 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”关键字只会限制某些(过长的)字符串有效。如果实例是数字、布尔值、空值、数组或对象,则关键字将通过验证。

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”的值必须是数字,代表数字实例的包含上限。

如果实例是数字,则此关键字仅当实例大于或正好等于“minimum”时才验证。

6.5. exclusiveMinimum

“exclusiveMinimum”的值必须是数字,代表数字实例的排他上限。

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

6.6. maxLength

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

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

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

6.7. minLength

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

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

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

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

6.8. pattern

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

如果正则表达式成功匹配实例,则字符串实例被认为是有效的。回想一下:正则表达式不会被隐式锚定。

6.9. items

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

此关键字决定数组中的子实例如何验证,而不会直接验证直接实例本身。

如果“items”是模式,则如果数组中的所有元素都成功地针对该模式进行验证,则验证成功。

如果“items”是模式数组,则如果实例的每个元素都针对相同位置的模式进行验证(如果有),则验证成功。

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

6.10. additionalItems

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

此关键字决定数组中的子实例如何验证,而不会直接验证直接实例本身。

如果“items”是模式数组,则如果每个实例元素在位置大于“items”的大小的情况下都针对“additionalItems”进行验证,则验证成功。

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

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

6.11. maxItems

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

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

6.12. minItems

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

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

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

6.13. uniqueItems

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

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

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

6.14. contains

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

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

6.15. maxProperties

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

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

6.16. minProperties

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

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

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

6.17. required

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

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

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

6.18. properties

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

此关键字决定对象中的子实例如何验证,而不会直接验证直接实例本身。

如果实例和此关键字的值中的名称都包含的每个名称,其子实例都针对相应的模式成功验证,则验证成功。

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

6.19. patternProperties

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

此关键字决定对象中的子实例如何验证,而不会直接验证直接实例本身。原始实例类型对此关键字的验证总是成功。

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

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

6.20. additionalProperties

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

此关键字决定对象中的子实例如何验证,而不会直接验证直接实例本身。

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

对于所有这些属性,如果子实例针对“additionalProperties”模式进行验证,则验证成功。

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

6.21. dependencies

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

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

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

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

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

6.22. propertyNames

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

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

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

6.23. enum

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

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

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

6.24. const

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

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

6.25. type

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

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

当且仅当实例属于此关键字列出的任何集合时,实例才有效。

6.26. allOf

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

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

6.27. anyOf

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

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

6.28. oneOf

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

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

6.29. not

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

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

7. 元数据关键字

7.1. definitions

此关键字的值必须是对象。该对象的每个成员值都必须是有效的 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”关键字。如果他们选择这样做

实现可以添加自定义格式属性。除非各方之间达成协议,否则模式作者不应期望对等实现支持此关键字和/或自定义格式属性。

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] 中定义的“点分十进制”ABNF 语法,则它对该属性有效。

8.3.5. ipv6

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

如果一个字符串实例符合 RFC 2373,第 2.2 节 [RFC2373] 中定义的 IPv6 地址表示法,则它对该属性有效。

8.3.6. uri

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

如果一个字符串实例是一个有效的 URI,根据 [RFC3986]

8.3.7. uri-reference

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

如果一个字符串实例是一个有效的 URI 引用(URI 或相对引用),根据 [RFC3986]

8.3.8. uri-template

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

如果一个字符串实例是一个有效的 URI 模板(任何级别),根据 [RFC6570]

8.3.9. json-pointer

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

如果一个字符串实例是一个有效的 JSON 指针,根据 [RFC6901]

9. 安全考虑

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

JSON Schema 验证允许使用正则表达式,而正则表达式有许多不同的(通常不兼容的)实现。一些实现允许嵌入任意代码,这超出了 JSON Schema 的范围,并且必须禁止。正则表达式通常也可以被设计成计算成本极高(所谓“灾难性回溯”),从而导致拒绝服务攻击。

10. 参考文献

10.1. 规范性引用

, "
[RFC2119] Bradner, S.RFC 中使用关键术语来指示需求级别,BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。
[json-schema]JSON Schema:一种描述 JSON 文档的媒体类型,互联网草案 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,"IPv6 地址体系结构",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]此节在离开互联网草案状态之前将被删除。

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]