互联网工程任务组 A. Wright,编辑
互联网草案
预期状态:信息性 H. Andrews,编辑
过期时间:2018 年 9 月 20 日 Cloudflare, Inc.
G. Luff
2018 年 3 月 19 日

JSON Schema 验证:用于 JSON 结构验证的词汇表
draft-handrews-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/。

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

此互联网草案将于 2018 年 9 月 20 日过期。

版权声明

版权所有 (c) 2018 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. 概述

JSON Schema 验证将模式应用于实例中的位置,并在每个位置对数据的结构进行断言约束。满足所有断言约束的实例位置将使用包含非断言信息的任何关键字进行注释,例如描述性元数据和使用提示。如果实例中的所有位置都满足所有断言约束,则称该实例相对于该模式是有效的。

每个模式对象独立地针对它所应用的每个实例位置进行评估。这通过确保验证器不需要在整个文档范围的验证过程中维护状态,从而极大地简化了验证器的实现要求。

3.1. 适用性

验证从将根模式应用于完整的实例文档开始。从那里,各种关键字用于确定将哪些其他子模式应用于当前位置或子位置。这些关键字还定义了子模式断言结果是否以及如何修改和/或组合。此类关键字本身不断言条件。相反,它们控制断言的应用和评估方式。

本文档的 布尔逻辑 [logic]条件 [conditional] 部分中的关键字将子模式应用于与父模式相同的位置。前者定义了子模式断言结果的布尔运算,而后者评估一个子模式,并使用其断言结果来确定要应用的另外两个子模式中的哪一个。

几个关键字确定将哪些子模式应用于数组项、对象属性值和对象属性名称。它们是:“items”、“additionalItems”、“contains”、“properties”、“patternProperties”、“additionalProperties”和“propertyNames”。“contains”关键字只要求其子模式相对于至少一个子实例有效,而其他关键字要求所有子模式相对于它们所应用的所有子实例有效。

3.1.1. 关键字独立性

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

为了方便模式作者,在控制子模式适用性的关键字中有一些例外

3.2. 断言

验证是检查断言的过程。每个断言都会添加实例必须满足的约束才能成功验证。

不存在的断言关键字永远不会限制验证。在某些情况下,这种无操作行为与存在具有特定值的关键字相同,并且已知这些值将在适当的地方进行说明。

通用 [general]数值 [numeric]字符串 [string] 部分中的所有关键字都是断言,以及“minItems”、“maxItems”、“uniqueItems”、“minProperties”、“maxProperties”和“required”。此外,“dependencies”是条件关键字和断言关键字组合的简写。

“format”、“contentType”和“contentEncoding”关键字也可以作为断言实现,尽管该功能是本文档的可选部分,并且这些关键字传达了额外的非断言信息。

3.2.1. 断言和实例原始类型

大多数验证断言只约束特定原始类型内的值。当实例的类型不是关键字目标的类型时,实例被认为符合断言。

例如,“maxLength”关键字将仅限制某些(过长的)字符串成为有效字符串。如果实例是数字、布尔值、空值、数组或对象,则它相对于此断言是有效的。

3.3. 注释

除了断言之外,本文档还提供了一小部分元数据关键字词汇表,可用于使用有用的信息对 JSON 实例进行注释。 第 7 节第 8 节 中的关键字也可用作注释,以及可选的断言,因为它们传达了有关实例数据的额外使用指南。

适用于实例中特定位置的模式,根据该模式,实例位置有效,将它的注释附加到实例中的该位置。由于许多子模式可以适用于任何单个位置,因此注释关键字需要指定对关键字的多个适用出现(具有不同的值)的任何不寻常处理。默认行为只是收集所有值。

其他词汇表 SHOULD 利用这种机制将它们自己的注释应用于实例。

3.3.1. 注释和验证结果

只要实例相对于模式对象及其所有父模式有效,就会收集注释。

特别是,在任何深度包含在 "not" 中的子模式中的注释,包括任何数量的中间附加 "not" 子模式,MUST 被忽略。如果实例相对于 "not" 子模式有效,那么根据定义它不与包含 "not" 的模式有效,因此不会使用 "not" 子模式的注释。

类似地,即使实例成功验证相对于完整的模式文档,"oneOf"、"anyOf"、"then" 或 "else" 的失败分支中的注释 MUST 被忽略。

3.3.2. 注释和短路验证

注释关键字 MUST 应用于所有可能的子实例。即使这种应用可以被短路,当只需要断言评估时。例如,"contains" 关键字只需要检查断言,直到至少一个数组项被证明有效。但是,当使用注释时,必须评估数组中的所有项以确定应将注释与哪些项关联。

4. 互操作性考虑

4.1. 字符串实例的验证

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

4.2. 数字实例的验证

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

4.3. 正则表达式

两个验证关键字 "pattern" 和 "patternProperties" 使用正则表达式来表达约束,而 "format" 关键字的 "regex" 值将实例值约束为正则表达式。这些正则表达式 SHOULD 符合 ECMA 262 [ecma262] 正则表达式方言。

此外,鉴于正则表达式结构支持的巨大差异,模式作者 SHOULD 将自己限制在以下正则表达式标记中

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

5. 元模式

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

6. 验证关键字

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

6.1. 任何实例类型的验证关键字

6.1.1. type

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

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

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

6.1.2. enum

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

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

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

6.1.3. const

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

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

6.2. 数字实例的验证关键字(number 和 integer)

6.2.1. multipleOf

"multipleOf" 的值 MUST 是一个严格大于 0 的数字。

仅当用此关键字的值除以数字实例结果为整数时,数字实例才有效。

6.2.2. maximum

"maximum" 的值 MUST 是一个数字,表示数字实例的包含上限。

如果实例是一个数字,那么此关键字仅在实例小于或正好等于 "maximum" 时才验证。

6.2.3. exclusiveMaximum

"exclusiveMaximum" 的值 MUST 是一个数字,表示数字实例的排他上限。

如果实例是一个数字,那么仅当实例的值严格小于(不等于)"exclusiveMaximum" 时,实例才有效。

6.2.4. minimum

"minimum" 的值 MUST 是一个数字,表示数字实例的包含下限。

如果实例是一个数字,那么此关键字仅在实例大于或正好等于 "minimum" 时才验证。

6.2.5. exclusiveMinimum

"exclusiveMinimum" 的值 MUST 是一个数字,表示数字实例的排他下限。

如果实例是一个数字,那么仅当实例的值严格大于(不等于)"exclusiveMinimum" 时,实例才有效。

6.3. 字符串的验证关键字

6.3.1. maxLength

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

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

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

6.3.2. minLength

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

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

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

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

6.3.3. pattern

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

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

6.4. 数组的验证关键字

6.4.1. items

"items" 的值 MUST 是一个有效的 JSON Schema 或一个有效的 JSON Schema 数组。

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

如果 "items" 是一个模式,则如果数组中的所有元素都成功验证相对于该模式,则验证成功。

如果 "items" 是一个模式数组,则如果实例的每个元素都验证相对于相同位置的模式(如果有),则验证成功。

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

6.4.2. additionalItems

"additionalItems" 的值 MUST 是一个有效的 JSON Schema。

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

如果 "items" 是一个模式数组,则如果大于 "items" 大小的每个实例元素都验证相对于 "additionalItems",则验证成功。

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

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

6.4.3. maxItems

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

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

6.4.4. minItems

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

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

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

6.4.5. uniqueItems

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

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

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

6.4.6. contains

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

如果数组实例中的至少一个元素相对于给定的模式有效,则该数组实例相对于 "contains" 有效。

6.5. 对象的验证关键字

6.5.1. maxProperties

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

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

6.5.2. minProperties

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

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

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

6.5.3. required

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

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

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

6.5.4. properties

"properties" 的值 MUST 是一个对象。此对象的每个值 MUST 是一个有效的 JSON Schema。

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

如果对于出现在实例中以及作为此关键字值中的名称的每个名称,该名称的子实例都成功验证相对于相应的模式,则验证成功。

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

6.5.5. patternProperties

"patternProperties" 的值 MUST 是一个对象。此对象的每个属性名称 SHOULD 是一个有效的正则表达式,符合 ECMA 262 正则表达式方言。此对象的每个属性值 MUST 是一个有效的 JSON Schema。

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

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

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

6.5.6. additionalProperties

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

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

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

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

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

6.5.7. 依赖项

[CREF1]此关键字可以拆分为两个,其中使用属性名称数组而不是子架构获得新名称的变体。双重行为令人困惑且相对难以实现。在之前的草案中,我们建议完全放弃该关键字,或放弃其中的一种形式,但我们收到了保留该关键字的支持反馈。有关更多讨论,请参阅 <https://github.com/json-schema-org/json-schema-spec/issues> 上的 issue #442 和 #528。鼓励提供进一步的反馈。

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

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

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

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

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

6.5.8. 属性名称

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

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

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

6.6. 用于有条件地应用子架构的关键字

这些关键字协同工作,根据另一个子架构的结果实现子架构的有条件应用。

这些关键字不得跨子架构边界相互交互。换句话说,一个 “allOf” 分支中的 “if” 不得影响另一个分支中的 “then” 或 “else”。

当这些关键字不存在时,它们没有任何默认行为。特别是,它们不得被视为存在带有空架构,并且当 “if” 不存在时, “then” 和 “else” 都必须完全被忽略。

6.6.1. if

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

此关键字的子架构的验证结果对整体验证结果没有直接影响。相反,它控制评估 “then” 或 “else” 关键字中的哪一个。

成功根据此关键字的子架构进行验证的实例还必须根据 “then” 关键字的子架构值进行验证,如果存在的话。

未能根据此关键字的子架构进行验证的实例还必须根据 “else” 关键字的子架构值进行验证,如果存在的话。

如果正在收集 注释 [annotations],则它们以通常的方式从此关键字的子架构中收集,包括当关键字存在而没有 “then” 或 “else” 时。

6.6.2. then

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

当 “if” 存在,并且实例成功根据其子架构进行验证时,如果实例也成功根据此关键字的子架构进行验证,则针对此关键字的验证成功。

当 “if” 不存在,或当实例未能根据其子架构进行验证时,此关键字没有任何影响。在这种情况下,实现不得为了验证或注释收集目的而根据此关键字评估实例。

6.6.3. else

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

当 “if” 存在,并且实例未能根据其子架构进行验证时,如果实例成功根据此关键字的子架构进行验证,则针对此关键字的验证成功。

当 “if” 不存在,或当实例成功根据其子架构进行验证时,此关键字没有任何影响。在这种情况下,实现不得为了验证或注释收集目的而根据此关键字评估实例。

6.7. 用于使用布尔逻辑应用子架构的关键字

6.7.1. allOf

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

如果实例成功根据此关键字的值定义的所有架构进行验证,则它成功根据此关键字进行验证。

6.7.2. anyOf

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

如果实例成功根据此关键字的值定义的至少一个架构进行验证,则它成功根据此关键字进行验证。

6.7.3. oneOf

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

如果实例成功根据此关键字的值定义的恰好一个架构进行验证,则它成功根据此关键字进行验证。

6.7.4. not

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

如果实例未能成功根据此关键字定义的架构进行验证,则它根据此关键字有效。

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

7.1. 前言

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

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

7.2. 实现要求

“format” 关键字既充当注释 (第 3.3 节),也充当断言 (第 3.2 节)。虽然不需要特别努力将其作为传达语义的注释来实现,但实现验证并非易事。

实现可以支持 “format” 关键字作为验证断言。如果它们选择这样做,

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

7.3. 定义的格式

7.3.1. 日期和时间

这些属性适用于字符串实例。

日期和时间格式名称源自 RFC 3339,第 5.6 节 [RFC3339]

支持格式的实现应实现对以下属性的支持

date-time
如果字符串实例根据 “date-time” 产生式是有效的表示,则它根据此属性有效。
date
如果字符串实例根据 “full-date” 产生式是有效的表示,则它根据此属性有效。
time
如果字符串实例根据 “full-time” 产生式是有效的表示,则它根据此属性有效。

实现可以支持使用该部分中定义的其他产生式名称的附加属性。如果实现了 “full-date” 或 “full-time”,则必须实现相应的简短形式(分别为 “date” 或 “time”),并且必须具有相同的行为。实现不得定义任何名称与 RFC 3339 产生式匹配的扩展属性,除非它根据该产生式的规则进行验证。 [CREF2]目前尚未就支持所有 RFC 3339 格式的必要性达成共识,因此这种保留命名空间的方法将鼓励进行实验,而不会承诺使用整个集合。要么格式实现要求将变得更加灵活,要么这些要求可能会被提升为完全指定的属性,或者被放弃。

7.3.2. 电子邮件地址

这些属性适用于字符串实例。

如果字符串实例是有效的 Internet 电子邮件地址,如下所示,则它根据这些属性有效

email
RFC 5322,第 3.4.1 节 [RFC5322] 所定义。
idn-email
RFC 6531 [RFC6531] 所定义

请注意,所有根据 “email” 属性有效的字符串也根据 “idn-email” 属性有效。

7.3.3. 主机名

这些属性适用于字符串实例。

如果字符串实例是 Internet 主机名的有效表示,如下所示,则它根据这些属性有效

hostname
RFC 1034,第 3.1 节 [RFC1034] 所定义,包括使用 RFC 5891,第 4.4 节 [RFC5891] 中指定的 Punycode 算法生成的 hostname。
idn-hostname
如 RFC 1034 中针对 hostname 所定义,或如 RFC 5890,第 2.3.2.3 节 [RFC5890] 中所定义的国际化 hostname。

请注意,所有根据 “hostname” 属性有效的字符串也根据 “idn-hostname” 属性有效。

7.3.4. IP 地址

这些属性适用于字符串实例。

如果字符串实例是 IP 地址的有效表示,如下所示,则它根据这些属性有效

ipv4
根据 RFC 2673,第 3.2 节 [RFC2673] 中定义的 “dotted-quad” ABNF 语法进行的 IPv4 地址。
ipv6
RFC 4291,第 2.2 节 [RFC4291] 中所定义的 IPv6 地址。

7.3.5. 资源标识符

这些属性适用于字符串实例。

uri
如果字符串实例是有效的 URI,根据 [RFC3986],则它根据此属性有效。
uri-reference
如果字符串实例是有效的 URI 引用(URI 或相对引用),根据 [RFC3986],则它根据此属性有效。
iri
如果字符串实例是有效的 IRI,根据 [RFC3987],则它根据此属性有效。
iri-reference
如果字符串实例是有效的 IRI 引用(IRI 或相对引用),根据 [RFC3987],则它根据此属性有效。

请注意,所有有效的 URI 都是有效的 IRI,所有有效的 URI 引用也是有效的 IRI 引用。

7.3.6. uri-template

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

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

请注意,URI 模板可用于 IRI;没有单独的 IRI 模板规范。

7.3.7. JSON 指针

这些属性适用于字符串实例。

json-pointer
如果字符串实例是 JSON 指针的有效 JSON 字符串表示,根据 RFC 6901,第 5 节 [RFC6901],则它根据此属性有效。
relative-json-pointer
如果字符串实例是有效的 相对 JSON 指针 [relative-json-pointer],则它根据此属性有效。

为了允许使用绝对和相对 JSON 指针,请使用 “anyOf” 或 “oneOf” 来指示对两种格式的支持。

7.3.8. regex

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

正则表达式,它应根据 ECMA 262 [ecma262] 正则表达式方言有效。

验证格式的实现必须至少接受 ECMA 262 在本规范的 正则表达式 [regexInterop] 部分中定义的子集,并且应该接受所有有效的 ECMA 262 表达式。

8. 字符串编码非 JSON 数据

8.1. 前言

在本节中定义的属性表明实例包含以 JSON 字符串编码的非 JSON 数据。它们描述了内容的类型以及编码方式。

这些属性提供了将 JSON 数据解释为丰富多媒体文档所需的额外信息。

8.2. 实现要求

内容关键字既充当注释 (第 3.3 节) 又充当断言 (第 3.2 节)。虽然不需要特别努力来将它们实现为注释,以传达应用程序如何解释字符串中的数据,但实现对媒体类型和编码的符合性验证并非易事。

实现可以支持 "contentMediaType" 和 "contentEncoding" 关键字作为验证断言。如果它们选择这样做,它们应该提供禁用这些关键字验证的选项。

8.3. contentEncoding

如果实例值为字符串,则此属性定义该字符串应该解释为二进制数据,并使用此属性命名的编码进行解码。 RFC 2045,第 6.1 节 [RFC2045] 列出了此属性的可能值。

此属性的值必须是字符串。

如果描述的实例不是字符串,则此属性的值应该被忽略。

8.4. contentMediaType

此属性的值必须是媒体类型,如 RFC 2046 [RFC2046] 所定义。此属性定义了此模式定义的实例的媒体类型。

此属性的值必须是字符串。

如果描述的实例不是字符串,则此属性的值应该被忽略。

如果 "contentEncoding" 属性不存在,但实例值为字符串,则此属性的值应该指定文本文档类型,并且字符集应该是在其中解码 JSON 字符串值的字符集(默认值为 Unicode)。

8.5. 示例

这是一个模式示例,说明了 "contentEncoding" 和 "contentMediaType" 的使用。

{
    "type": "string",
    "contentEncoding": "base64",
    "contentMediaType": "image/png"
}

                    

此模式描述的实例应该是字符串,并且它们的值应该可以解释为 base64 编码的 PNG 图片。

另一个示例

{
    "type": "string",
    "contentMediaType": "text/html"
}

                    

此模式描述的实例应该是包含 HTML 的字符串,使用 JSON 字符串解码到的任何字符集(默认值为 Unicode)。

9. 使用 "definitions" 重用模式

"definitions" 关键字为模式作者提供了一个标准位置,以便将可重用的 JSON 模式内联到更通用的模式中。该关键字不会直接影响验证结果。

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

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

                    

例如,以下是一个模式,它描述了正整数数组,其中正整数约束是 "definitions" 中的子模式。

10. 模式注释

模式验证是一种有用的机制,用于使用附加信息注释实例数据。确定何时以及如何将注释与实例相关联的规则在 第 3.3 节 中概述。

这些通用注释关键字提供了用于文档和用户界面显示目的的常用信息。它们并非旨在形成一组全面的功能。相反,可以定义额外的词汇表,用于更复杂的基于注释的应用程序。

10.1. "title" 和 "description"

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

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

10.2. "default"

此关键字的值没有限制。当此关键字的多个出现适用于单个子实例时,实现应该删除重复项。

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

10.3. "readOnly" 和 "writeOnly"

这些关键字的值必须是布尔值。当这些关键字的多个出现适用于单个子实例时,如果任何出现指定了 true 值,则结果值必须为 true,否则必须为 false。

如果 "readOnly" 的值为布尔值 true,则表示实例的值完全由拥有机构管理,并且应用程序尝试修改此属性的值预期会被该拥有机构忽略或拒绝。

标记为 "readOnly" 的整个文档的实例文档可能会在发送给拥有机构时被忽略,或者可能会根据机构的决定导致错误。

如果 "writeOnly" 的值为布尔值 true,则表示在从拥有机构检索实例时,该值永远不会出现。它可以在发送给拥有机构以更新或创建文档(或它代表的资源)时出现,但它不会包含在任何更新或新创建的实例版本中。

标记为 "writeOnly" 的整个文档的实例文档可能会以某种空白文档的形式返回,或者在检索时可能会产生错误,或者使检索请求被忽略,具体取决于机构的决定。

例如,"readOnly" 用于将数据库生成的序列号标记为只读,而 "writeOnly" 用于将密码输入字段标记为只写。

这些关键字可用于帮助用户界面实例生成。特别是,应用程序可以选择使用一个控件,该控件在写入字段时隐藏输入值。

省略这些关键字与 false 值具有相同行为。

10.4. "examples"

此关键字的值必须是数组。数组中的值没有限制。当此关键字的多个出现适用于单个子实例时,实现必须提供所有值的扁平数组,而不是数组的数组。

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

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

11. 安全注意事项

JSON 模式验证定义了 JSON 模式核心的词汇表,并且涉及到那里列出的所有安全注意事项。

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

支持根据 "contentEncoding" 和/或 "contentMediaType" 验证或评估实例字符串数据的实现,有可能以不安全的方式基于误导性信息评估数据。应用程序可以通过仅在建立模式和实例之间的关系时(例如,它们共享相同的机构)执行此类处理来降低这种风险。

处理媒体类型或编码受该媒体类型或编码的安全注意事项的约束。例如,当处理 JSON 字符串中编码的 JavaScript 或 ECMAScript 时,RFC 4329 脚本媒体类型 [RFC4329] 的安全注意事项适用。

12. 参考资料

12.1. 规范性引用

, "
[RFC2119] Bradner, S.,"用于 RFC 中指示需求级别的关键词",BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。
[RFC1034] Mockapetris, P.,"域名 - 概念和功能",STD 13,RFC 1034,DOI 10.17487/RFC1034,1987 年 11 月。
[RFC2045] Freed, N.N. Borenstein,"多用途互联网邮件扩展 (MIME) 第一部分:互联网消息正文格式",RFC 2045,DOI 10.17487/RFC2045,1996 年 11 月。
[RFC2046] Freed, N.N. Borenstein,"多用途互联网邮件扩展 (MIME) 第二部分:媒体类型",RFC 2046,DOI 10.17487/RFC2046,1996 年 11 月。
[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 月。
[RFC3987] Duerst, M.M. Suignard,"国际化资源标识符 (IRI)",RFC 3987,DOI 10.17487/RFC3987,2005 年 1 月。
[RFC4291] Hinden, R.S. Deering,"IPv6 地址架构",RFC 4291,DOI 10.17487/RFC4291,2006 年 2 月。
[RFC5322] Resnick, P.,"互联网消息格式",RFC 5322,DOI 10.17487/RFC5322,2008 年 10 月。
[RFC5890] Klensin, J.,"应用程序的国际化域名 (IDNA):定义和文档框架",RFC 5890,DOI 10.17487/RFC5890,2010 年 8 月。
[RFC5891] Klensin, J.,"应用程序中的国际化域名 (IDNA):协议",RFC 5891,DOI 10.17487/RFC5891,2010 年 8 月。
[RFC6570] Gregorio, J.Fielding, R.Hadley, M.Nottingham, M.D. Orchard,"URI 模板",RFC 6570,DOI 10.17487/RFC6570,2012 年 3 月。
[RFC6531] Yao, J.W. Mao,"国际化电子邮件的 SMTP 扩展",RFC 6531,DOI 10.17487/RFC6531,2012 年 2 月。
[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 月。
[ecma262]ECMA 262 规范"
[relative-json-pointer] Luff, G.H. Andrews,"相对 JSON 指针",互联网草案 draft-handrews-relative-json-pointer-01,2017 年 11 月。
[json-schema] Wright, A.H. Andrews,"JSON 模式:描述 JSON 文档的媒体类型",互联网草案 draft-handrews-json-schema-01,2017 年 11 月。

12.2. 说明性引用

[RFC4329] Hoehrmann, B.,"脚本媒体类型",RFC 4329,DOI 10.17487/RFC4329,2006 年 4 月。

附录 A. 致谢

感谢 Gary Court、Francis Galiegue、Kris Zyp 和 Geraint Luff 对 JSON 模式初始草案的工作。

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

附录 B. 变更日志

[CREF3]本节将在离开 Internet 草案状态前删除。

draft-handrews-json-schema-validation-01

draft-handrews-json-schema-validation-00

draft-wright-json-schema-validation-01

draft-wright-json-schema-validation-00

draft-fge-json-schema-validation-00

作者地址

Austin Wright (编辑) 电子邮件:[email protected]
Henry Andrews (编辑) Cloudflare, Inc. 旧金山, 加利福尼亚州 美国 电子邮件:[email protected]
Geraint Luff 剑桥, 英国 电子邮件:[email protected]