互联网草案 JSON 模式验证 2022 年 6 月
Wright 等人 2022 年 12 月 18 日失效 [页]
工作组
互联网工程任务组
互联网草案
draft-bhutton-json-schema-validation-01
已发布
预期状态
信息性
失效日期
作者
A. Wright,
H. Andrews,
B. Hutton,
Postman

JSON 模式验证:用于 JSON 结构验证的词汇

摘要

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

致读者

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

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

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

本备忘录的状态

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

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

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

此互联网草案将于 2022 年 12 月 18 日失效。

目录

1. 简介

JSON 模式可用于要求给定的 JSON 文档(实例)满足一定数量的条件。这些条件通过使用本文档中描述的关键字进行断言。此外,还定义了一组关键字,以协助交互式用户界面实例生成。

本文档将使用由 JSON 模式核心 [json-schema] 规范定义的概念、语法和术语。

2. 约定和术语

本文档中的关键词“必须”、“不得”、“需要”、“应”、“不应”、“建议”、“不建议”、“推荐”、“可”和“可选”的解释方式如 RFC 2119 [RFC2119] 中所述。

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

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

3. 概述

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

每个模式对象都会独立地针对其适用的每个实例位置进行评估。这极大地简化了验证器的实现要求,因为它确保验证器不需要在整个文档验证过程中维护状态。

本规范定义了一组断言关键字,以及一小部分元数据关键字,这些关键字可用于为 JSON 实例添加有用的信息。 第 7 节 关键字主要用作注释,但可以选择用作断言。 第 8 节 关键字是用于处理作为 JSON 字符串嵌入的文档的注释。

4. 互操作性注意事项

4.1. 字符串实例的验证

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

4.2. 数值实例的验证

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

4.3. 正则表达式

使用正则表达式的关键字,或将实例值限制为正则表达式的关键字,受 JSON Schema 核心 [json-schema] 规范中正则表达式互操作性注意事项的约束。

5. 元模式

默认 JSON Schema 方言元模式的当前 URI 为 https://json-schema.fullstack.org.cn/draft/2020-12/schema。为了方便模式作者,此元模式描述了一种方言,它包含本规范和 JSON Schema 核心规范中定义的所有词汇表,以及两个用于过渡期的保留关键字。每个部分下面都给出了单个词汇表和词汇表元模式 URI。某些词汇表是可选支持的,这将在相关部分中详细说明。

为了纠正错误,可以在规范草案之间发布更新的词汇表和元模式 URI。实现应该考虑在此规范草案之后和下一个草案之前发布的日期后的 URI,以指示与这里列出的 URI 相同的语法和语义。

6. 结构验证词汇表

模式中的验证关键字对实例的成功验证施加要求。这些关键字都是断言,没有注释行为。

不使用 "$vocabulary" 的元模式应该被认为需要这个词汇表,就像它的 URI 存在且值为 true 一样。

此词汇表的当前 URI(称为验证词汇表)为:<https://json-schema.fullstack.org.cn/draft/2020-12/vocab/validation>。

相应元模式的当前 URI 为:https://json-schema.fullstack.org.cn/draft/2020-12/meta/validation

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

6.1.1. 类型

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

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

如果“type”的值是字符串,那么当实例的类型与字符串的值表示的类型匹配时,实例验证成功。如果“type”的值是数组,那么当实例的类型与数组中字符串指示的任何类型匹配时,实例验证成功。

6.1.2. 枚举

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

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

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

6.1.3. 常量

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

使用此关键字在功能上等同于具有单个值的 "enum" (第 6.1.2 节)

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

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

6.2.1. 倍数

“multipleOf”的值必须是严格大于 0 的数字。

数值实例仅在除以此关键字的值时得到整数时才有效。

6.2.2. 最大值

“maximum”的值必须是数字,代表数值实例的包含上限。

如果实例是数字,则此关键字仅在实例小于或等于“maximum”时才验证。

6.2.3. 独占最大值

“exclusiveMaximum”的值必须是数字,代表数值实例的独占上限。

如果实例是数字,那么实例仅当其值严格小于(不等于)“exclusiveMaximum”时才有效。

6.2.4. 最小值

“minimum”的值必须是数字,代表数值实例的包含下限。

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

6.2.5. 独占最小值

“exclusiveMinimum”的值必须是数字,代表数值实例的独占下限。

如果实例是数字,那么实例仅当其值严格大于(不等于)“exclusiveMinimum”时才有效。

6.3. 字符串的验证关键字

6.3.1. 最大长度

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

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

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

6.3.2. 最小长度

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

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

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

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

6.3.3. 模式

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

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

6.4. 数组的验证关键字

6.4.1. 最大项数

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

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

6.4.2. 最小项数

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

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

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

6.4.3. 唯一项

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

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

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

6.4.4. 最大包含数

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

如果“contains”未出现在同一个模式对象中,则此关键字无效。

实例数组针对“maxContains”的有效性取决于相邻"contains" [json-schema]关键字的注释结果形式,共有两种方式。第一种方式是,如果注释结果是一个数组,并且该数组的长度小于或等于“maxContains”的值。第二种方式是,如果注释结果是布尔值“true”,并且实例数组的长度小于或等于“maxContains”的值。

6.4.5. minContains

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

如果同一个模式对象中不存在“contains”,则此关键字无效。

实例数组针对“minContains”的有效性取决于相邻"contains" [json-schema]关键字的注释结果形式,共有两种方式。第一种方式是,如果注释结果是一个数组,并且该数组的长度大于或等于“minContains”的值。第二种方式是,如果注释结果是布尔值“true”,并且实例数组的长度大于或等于“minContains”的值。

允许值为 0,但这仅用于设置从 0 到“maxContains”值的出现范围。值为 0 会导致“minContains”和“contains”始终通过验证(但验证仍可能针对“maxContains”关键字失败)。

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

6.5. 对象验证关键字

6.5.1. maxProperties

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

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

6.5.2. minProperties

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

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

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

6.5.3. required

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

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

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

6.5.4. dependentRequired

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

此关键字指定如果存在特定其他属性,则需要哪些属性。它们的要求取决于其他属性是否存在。

如果在实例和此关键字的值中均出现每个名称,则对应数组中的每一项也是实例中属性的名称,则验证成功。

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

7. 用于语义内容的词汇表 - “format”

7.1. 前言

仅结构验证可能不足以使应用程序正确使用某些值。“format”注释关键字旨在允许模式作者为值的固定子集传达语义信息,这些值可以通过权威资源(无论是 RFC 还是其他外部规范)准确描述。

此关键字的值称为格式属性。它必须是字符串。格式属性通常只能验证给定的一组实例类型。如果要验证的实例的类型不在此集中,则应针对此格式属性和实例的验证成功。本节中定义的所有格式属性都适用于字符串,但可以指定格式属性应用于 核心 JSON Schema [json-schema] 中定义的任何实例类型。 请注意,此规范中的“type”关键字定义了一个“integer”类型,它不是数据模型的一部分。因此,格式属性可以限于数字,但不能专门限于整数。但是,可以将数字格式与值为“integer”的“type”关键字一起使用,或者可以明确定义为始终通过(如果数字不是整数),这与仅应用于整数的本质行为相同。

此词汇表(称为格式注释词汇表)的当前 URI 为:<https://json-schema.fullstack.org.cn/draft/2020-12/vocab/format-annotation>。相应元模式的当前 URI 为:https://json-schema.fullstack.org.cn/draft/2020-12/meta/format-annotation。要求实施支持此词汇表。

除了格式注释词汇表之外,还可以使用另一个词汇表为自定义元模式定义“format”作为断言。格式断言词汇表的 URI 为:<https://json-schema.fullstack.org.cn/draft/2020-12/vocab/format-assertion>。相应元模式的当前 URI 为:https://json-schema.fullstack.org.cn/draft/2020-12/meta/format-assertion。实施支持格式断言词汇表是可选的。

同时指定格式注释和格式断言词汇表在功能上等同于仅指定格式断言词汇表,因为它的要求是格式注释词汇表的超集。

7.2. 实施要求

“format”关键字的功能由引用的词汇表定义。

7.2.1. 格式注释词汇表

如果实施支持注释收集,则必须收集格式的值作为注释。这使得应用程序级验证成为可能,即使模式验证不可用或不足。

实施可能仍然将“format”视为断言,除了注释之外,还尝试验证值对指定语义的符合性。实施必须提供选项来启用和禁用此类评估,并且必须在默认情况下禁用。实施应记录它们对此类验证的支持级别。 指定格式注释词汇表并在实施中启用验证不应被视为等同于指定格式断言词汇表,因为当未指定格式断言词汇表时,实施不需要提供完整的验证支持。

当实施配置为断言行为时,它:

  • 应为下面定义的每个格式属性提供特定于实施的尽力而为的验证;
  • 可以将所有格式属性的验证实现为无操作,通过始终生成 true 的验证结果;

这与实施的现状相匹配,实施对某些或所有格式属性提供了广泛的验证级别,包括根本不验证。它还旨在鼓励仅依赖注释行为并在应用程序中执行语义验证,这是推荐的最佳实践。

7.2.2. 格式断言词汇表

当格式断言词汇表使用值为 true 声明时,实施必须为本规范定义的所有格式提供完整的验证支持。无法提供完整的验证支持的实施必须拒绝处理模式。

支持格式断言词汇表的实施:

  • 如果实施支持注释收集,则仍必须将“format”收集为注释;
  • 必须将“format”评估为断言;
  • 必须为本规范中定义的所有格式属性以及它识别的任何其他格式属性实现语法验证,这样,正确的类型的可能实例值将导致验证失败。

对格式属性的最小验证要求是故意模糊和宽松的,因为许多属性都涉及复杂性。尤其要注意,该要求仅限于语法检查;不应期望实施发送电子邮件、尝试连接到 URL,或以其他方式检查格式实例标识的实体的存在。 预计对于诸如日期时间之类的简单格式,语法验证将是彻底的。对于诸如电子邮件地址之类的复杂格式,它是各种标准和众多调整随时间的积累,并且具有可能或可能不会受到使用值的应用程序限制的模糊和/或过时的规则,最小验证就足够了。例如,不包含“@”的实例字符串显然不是有效的电子邮件地址,而包含 7 位 ASCII 之外的字符的“email”或“hostname”同样明显无效。

建议实施对每种格式使用通用的解析库或众所周知的正则表达式。实施应明确记录如何以及在何种程度上验证每个格式属性。

标准核心和验证元模式 (第 5 节) 在其“$vocabulary”关键字中包含此词汇表,值为 false,因为默认情况下,实施不需要支持此关键字作为断言。使用值为 true 支持格式词汇表被理解为会大大增加代码大小,在某些情况下还会增加执行时间,并且不适合所有实施。

7.2.3. 自定义格式属性

实现 MAY 支持自定义格式属性。 除非双方之间达成一致,否则模式作者 SHALL NOT 预期对等实现支持此类自定义格式属性。 实现 MUST NOT 失败收集未知格式作为注释。 当格式断言词汇表被指定时,实现 MUST 在遇到未知格式时失败。

词汇表不支持专门为关键字声明不同的值集。 由于此限制以及此关键字在历史上实现的不一致性,如果需要互操作性,则 RECOMMENDED 在自定义词汇表中定义额外的关键字,而不是额外的格式属性。

7.3. 定义的格式

7.3.1. 日期、时间和持续时间

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

日期和时间格式名称取自 RFC 3339,第 5.6 节 [RFC3339]。 持续时间格式来自 RFC 3339 附录 A 中给出的 ISO 8601 ABNF。

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

date-time
如果字符串实例根据“date-time”ABNF 规则(如上所述)是有效表示,则它相对于此属性有效。
date
如果字符串实例根据“full-date”ABNF 规则(如上所述)是有效表示,则它相对于此属性有效。
time
如果字符串实例根据“full-time”ABNF 规则(如上所述)是有效表示,则它相对于此属性有效。
duration
如果字符串实例根据“duration”ABNF 规则(如上所述)是有效表示,则它相对于此属性有效。

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

7.3.2. 电子邮件地址

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

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

email
RFC 5321,第 4.1.2 节 [RFC5321] 中的“Mailbox”ABNF 规则所定义。
idn-email
RFC 6531,第 3.3 节 [RFC6531] 中扩展的“Mailbox”ABNF 规则所定义。

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

7.3.3. 主机名

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

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

hostname
RFC 1123,第 2.1 节 [RFC1123] 中所定义,包括使用 RFC 5891,第 4.4 节 [RFC5891] 中指定的 Punycode 算法生成的主机名。
idn-hostname
如 RFC 1123 中对主机名的定义,或如 RFC 5890,第 2.3.2.3 节 [RFC5890] 中所定义的国际化主机名。

请注意,所有相对于“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],则它相对于此属性有效。
uuid
如果字符串实例是 UUID 的有效字符串表示,根据 [RFC4122],则它相对于此属性有效。

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

另请注意,“uuid”格式用于普通 UUID,而不是 URN 中的 UUID。 例如“f81d4fae-7dec-11d0-a765-00a0c91e6bf6”。 对于作为 URN 的 UUID,请使用“uri”格式,并使用“pattern”正则表达式“^urn:uuid:”来指示 URI 方案和 URN 命名空间。

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

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

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

验证格式的实现 MUST 至少接受 正则表达式 (第 4.3 节) 部分中定义的 ECMA-262 子集,并且 SHOULD 接受所有有效的 ECMA-262 表达式。

8. 用于字符串编码数据内容的词汇表

8.1. 前言

本节中定义的注释表示实例包含以 JSON 字符串编码的非 JSON 数据。

这些属性提供了解释 JSON 数据作为丰富多媒体文档所需的其他信息。 它们描述了内容类型、编码方式和/或验证方式。 它们不作为验证断言;格式错误的字符串编码文档 MUST NOT 导致包含的实例被视为无效。

不使用“$vocabulary”的元模式 SHOULD 被视为需要此词汇表,就好像它的 URI 存在且值为 true 一样。

此词汇表的当前 URI(称为内容词汇表)为:<https://json-schema.fullstack.org.cn/draft/2020-12/vocab/content>。

相应元模式的当前 URI 为:https://json-schema.fullstack.org.cn/draft/2020-12/meta/content

8.2. 实现要求

由于安全和性能问题,以及可能的內容类型的开放性,实现 MUST NOT 默认自动解码、解析和/或验证字符串内容。 这还支持将嵌入式文档用于与处理包含文档的消费者不同的消费者进行处理的用例。

本节中的所有关键字仅适用于字符串,对其他数据类型没有影响。

实现 MAY 提供自动解码、解析和/或验证字符串内容的能力。 但是,它 MUST NOT 默认执行这些操作,并且 MUST 分别提供每个字符串编码文档的验证结果,而不是包含文档。 此过程 SHOULD 等同于完全评估实例与原始模式,然后使用注释对每个字符串编码文档进行解码、解析和/或验证。 现在,这种自动解码、解析和验证功能执行和返回解析数据和/或验证结果的确切机制尚未指定。 如果这种功能很受欢迎,它可能会在未来的草案中更全面地指定。

另请参阅安全注意事项 (第 10 节) 部分,了解根据这些关键字自动处理实例字符串可能引入的漏洞。

8.3. contentEncoding

如果实例值为字符串,则此属性定义该字符串应被解释为编码的二进制数据,并使用此属性命名的编码进行解码。

RFC 4648 [RFC4648] 列出了表示具有多种变体的 16、32 和 64 进制编码的可能值。此外,RFC 2045 [RFC2045] 的第 6.7 节和第 6.8 节提供了 MIME 中使用的编码。此关键字源自 MIME 的 Content-Transfer-Encoding 标头,该标头旨在将二进制数据映射到 ASCII 字符。它与 HTTP 的 Content-Encoding 标头无关,后者用于对 HTTP 请求和响应的内容进行编码(例如压缩或加密)。

由于“base64”在两个 RFC 中都有定义,因此除非字符串专门用于 MIME 上下文,否则应假设来自 RFC 4648 的定义。请注意,所有这些编码都生成仅包含 7 位 ASCII 字符的字符串。因此,对于包含该范围之外的字符的字符串,此关键字没有任何意义。

如果此关键字不存在,但“contentMediaType”存在,则表示编码是标识编码,这意味着不需要转换即可将内容表示为 UTF-8 字符串。

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

8.4. contentMediaType

如果实例是字符串,则此属性指示字符串内容的媒体类型。如果“contentEncoding”存在,则此属性描述解码后的字符串。

此属性的值必须是字符串,该字符串必须是媒体类型,如 RFC 2046 [RFC2046] 中所定义。

8.5. contentSchema

如果实例是字符串,并且“contentMediaType”存在,则此属性包含一个描述字符串结构的架构。

此关键字可以与任何可以映射到 JSON Schema 数据模型的媒体类型一起使用。

此属性的值必须是有效的 JSON 架构。如果“contentMediaType”不存在,则应忽略它。

8.6. 示例

以下是一个示例架构,说明了“contentEncoding”和“contentMediaType”的使用:

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

此架构描述的实例预计为字符串,并且其值应可解释为 base64 编码的 PNG 图像。

另一个示例:

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

此架构描述的实例预计为包含 HTML 的字符串,使用 JSON 字符串被解码成的任何字符集。根据 RFC 8259 [RFC8259] 的第 8.1 节,在完全封闭的系统之外,这必须是 UTF-8。

此示例描述了一个使用 HMAC SHA-256 算法进行 MAC 的 JWT,并且在其声明集中需要“iss”和“exp”字段。

{
    "type": "string",
    "contentMediaType": "application/jwt",
    "contentSchema": {
        "type": "array",
        "minItems": 2,
        "prefixItems": [
            {
                "const": {
                    "typ": "JWT",
                    "alg": "HS256"
                }
            },
            {
                "type": "object",
                "required": ["iss", "exp"],
                "properties": {
                    "iss": {"type": "string"},
                    "exp": {"type": "integer"}
                }
            }
        ]
    }
}

请注意,“contentEncoding”没有出现。虽然“application/jwt”媒体类型使用了 base64url 编码,但这是由媒体类型定义的,该媒体类型决定了如何将 JWT 字符串解码为两个 JSON 数据结构列表:首先是标头,然后是有效负载。由于 JWT 媒体类型确保 JWT 可以用 JSON 字符串表示,因此不需要进一步编码或解码。

9. 用于基本元数据的词汇表

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

不使用“$vocabulary”的元架构应被视为需要此词汇表,就好像它的 URI 存在且值为 true 一样。

此词汇表的当前 URI(称为元数据词汇表)为:<https://json-schema.fullstack.org.cn/draft/2020-12/vocab/meta-data>。

相应元架构的当前 URI 为:https://json-schema.fullstack.org.cn/draft/2020-12/meta/meta-data

9.1. "title" 和 "description"

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

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

9.2. "default"

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

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

9.3. "deprecated"

此关键字的值必须是布尔值。当此关键字的多个出现适用于单个子实例时,应用程序应考虑实例位置已弃用,如果任何出现指定的值为 true。

如果“deprecated”的值为布尔值 true,则表示应用程序应避免使用声明的属性。它可能意味着该属性将在将来被删除。

包含值为 true 的“deprecated”的根架构表示正在描述的整个资源可能在将来被删除。

“deprecated”关键字应用于每个实例位置,其中包含该关键字的架构对象成功应用于该位置。这可能导致以下情况:即使包含的数组或对象未弃用,但每个数组项或对象属性都已弃用。

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

9.4. "readOnly" 和 "writeOnly"

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

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

如果整个文档被标记为“readOnly”,则发送到拥有机构的实例文档可能会被忽略,也可能会导致错误,具体由机构决定。

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

如果整个文档被标记为“writeOnly”,则检索到的实例文档可能会作为某种空白文档返回,也可能会在检索时产生错误,或者检索请求可能会被忽略,具体由机构决定。

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

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

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

9.5. "examples"

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

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

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

10. 安全注意事项

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

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

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

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

11. 参考文献

11.1. 规范性引用

[RFC2119]
Bradner, S., "RFC 中用于指示需求级别的关键词", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC1123]
Braden, R., Ed., "互联网主机需求 - 应用与支持", STD 3, RFC 1123, DOI 10.17487/RFC1123, , <https://www.rfc-editor.org/info/rfc1123>.
[RFC2045]
Freed, N.N. Borenstein, "多用途互联网邮件扩展 (MIME) 第一部分:互联网消息主体格式", RFC 2045, DOI 10.17487/RFC2045, , <https://www.rfc-editor.org/info/rfc2045>.
[RFC2046]
Freed, N.N. Borenstein, "多用途互联网邮件扩展 (MIME) 第二部分:媒体类型", RFC 2046, DOI 10.17487/RFC2046, , <https://www.rfc-editor.org/info/rfc2046>.
[RFC2673]
Crawford, M., "域名系统中的二进制标签", RFC 2673, DOI 10.17487/RFC2673, , <https://www.rfc-editor.org/info/rfc2673>.
[RFC3339]
Klyne, G.C. Newman, "互联网上的日期和时间:时间戳", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/info/rfc3339>.
[RFC3986]
Berners-Lee, T., Fielding, R.L. Masinter, "通用资源标识符 (URI):通用语法", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>.
[RFC3987]
Duerst, M.M. Suignard, "国际化资源标识符 (IRI)", RFC 3987, DOI 10.17487/RFC3987, , <https://www.rfc-editor.org/info/rfc3987>.
[RFC4122]
Leach, P., Mealling, M.R. Salz, "通用唯一标识符 (UUID) URN 命名空间", RFC 4122, DOI 10.17487/RFC4122, , <https://www.rfc-editor.org/info/rfc4122>.
[RFC4291]
Hinden, R.S. Deering, "IPv6 地址体系结构", RFC 4291, DOI 10.17487/RFC4291, , <https://www.rfc-editor.org/info/rfc4291>.
[RFC4648]
Josefsson, S., "Base16、Base32 和 Base64 数据编码", RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/info/rfc4648>.
[RFC5321]
Klensin, J., "简单邮件传输协议", RFC 5321, DOI 10.17487/RFC5321, , <https://www.rfc-editor.org/info/rfc5321>.
[RFC5890]
Klensin, J., "应用程序的国际化域名 (IDNA):定义和文档框架", RFC 5890, DOI 10.17487/RFC5890, , <https://www.rfc-editor.org/info/rfc5890>.
[RFC5891]
Klensin, J., "应用程序中的国际化域名 (IDNA):协议", RFC 5891, DOI 10.17487/RFC5891, , <https://www.rfc-editor.org/info/rfc5891>.
[RFC6570]
Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.D. Orchard, "URI 模板", RFC 6570, DOI 10.17487/RFC6570, , <https://www.rfc-editor.org/info/rfc6570>.
[RFC6531]
Yao, J.W. Mao, "国际化电子邮件的 SMTP 扩展", RFC 6531, DOI 10.17487/RFC6531, , <https://www.rfc-editor.org/info/rfc6531>.
[RFC6901]
Bryan, P., Ed., Zyp, K.M. Nottingham, Ed., "JavaScript 对象表示法 (JSON) 指针", RFC 6901, DOI 10.17487/RFC6901, , <https://www.rfc-editor.org/info/rfc6901>.
[RFC8259]
Bray, T., Ed., "JavaScript 对象表示法 (JSON) 数据交换格式", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/info/rfc8259>.
[ecma262]
"ECMA-262,第 11 版规范", , <https://262.ecma-international.org/5.1/>.
[relative-json-pointer]
Luff, G., Andrews, H.B. Hutton, Ed., "相对 JSON 指针", 正在进行的工作, 互联网草案,draft-handrews-relative-json-pointer-01, , <https://datatracker.ietf.org/doc/html/draft-handrews-relative-json-pointer-01>.
[json-schema]
Wright, A., Andrews, H., Hutton, B.G. Dennis, "JSON Schema:描述 JSON 文档的媒体类型", 正在进行的工作, 互联网草案,draft-bhutton-json-schema-01, , <https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-01>.

11.2. 信息性引用

[RFC4329]
Hoehrmann, B., "脚本媒体类型", RFC 4329, DOI 10.17487/RFC4329, , <https://www.rfc-editor.org/info/rfc4329>.

附录 A. 从验证移到核心的关键字

从本草案开始,几个关键字已从本文件中移到 核心规范 [json-schema],在某些情况下会进行重命名或其他更改。这将影响以下以前的验证关键字:

"definitions"
重命名为 "$defs" 以匹配 "$ref" 并缩短类型。Schema 词汇表作者不应定义具有不同行为的 "definitions" 关键字,以避免使仍然使用旧名称的 Schema 无效。虽然本文件中引用的单词汇表元 Schema 中没有 "definitions",但它仍然存在于默认元 Schema 中,并且实现应假定 "$defs" 和 "definitions" 在使用该元 Schema 时具有相同行为。
"allOf"、"anyOf"、"oneOf"、"not"、"if"、"then"、"else"、"items"、"additionalItems"、"contains"、"propertyNames"、"properties"、"patternProperties"、"additionalProperties"
所有这些关键字都将子 Schema 应用于实例并组合其结果,而不会断言任何自身条件。如果没有断言关键字,这些应用器只能通过使用 false 布尔 Schema 或通过反转 true 布尔 Schema (或等效 Schema 对象) 的结果来导致断言失败。因此,最好将它们定义为验证、超 Schema 和扩展词汇表都可以基于的通用机制。
"dependencies"
此关键字有两种不同的行为模式,这使得它在实现和推理方面比较困难。Schema 形式已移到核心并重命名为 "dependentSchemas",作为应用器词汇表的一部分。它类似于 "properties",不同之处在于它不会将其子 Schema 应用于属性值,而是将其应用于包含该属性的对象。属性名称数组形式保留在这里并重命名为 "dependentRequired",因为它是一个断言,它是 "required" 断言关键字的条件使用的快捷方式。

附录 B. 致谢

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

感谢 Jason Desrosiers、Daniel Perrett、Erik Wilde、Evgeny Poberezkin、Brad Bowman、Gowry Sankar、Donald Pipowitch、Dave Finlay、Denis Laxalde、Phil Sturgeon、Shawn Silverman 和 Karen Etheridge 对文档的提交和修补。

附录 C. 变更日志

在离开互联网草案状态之前,应删除本节。

draft-bhutton-json-schema-validation-01
  • 改进和澄清 "minContains" 关键字的解释
  • 删除 "production" 的使用,改为 "ABNF 规则"
draft-bhutton-json-schema-validation-00
  • 将电子邮件格式 RFC 引用更正为 5321,而不是 5322
  • 澄清 "contentEncoding" 值的集合和含义
  • 参考 ECMA-262,第 11 版,以了解正则表达式支持
  • 将 "format" 拆分为仅注释词汇表和断言词汇表
  • 澄清 "deprecated" 在适用于数组时的含义
draft-handrews-json-schema-validation-02
  • 将关键字分组到正式词汇表中
  • 更新 "format" 的词汇表实现要求
  • 默认情况下,"format" 不得验证,但可以启用验证
  • 可以使用词汇表声明来要求 "format" 验证
  • 将 "definitions" 移到核心规范中,作为 "$defs"
  • 将应用器关键字移动到核心规范
  • 将“dependencies”的数组形式重命名为“dependentRequired”,并将模式形式移动到核心规范
  • 将所有“content*”关键字指定为注释,而不是断言
  • 添加“contentSchema”以允许将模式应用于字符串编码的文档
  • 还允许在“contentEncoding”中使用 RFC 4648 编码
  • 添加“minContains”和“maxContains”
  • 更新“hostname”和“idn-hostname”的 RFC 参考
  • 添加“uuid”和“duration”格式
draft-handrews-json-schema-validation-01
  • 此草案纯粹是澄清,没有功能上的改变
  • 提供了在“not”和类似情况下忽略注释背后的通用原则
  • 阐明了“if”/“then”/“else”验证交互
  • 阐明了“if”/“then”/“else”对注释的行为
  • 轻微的格式和交叉引用改进
draft-handrews-json-schema-validation-00
  • 添加了“if”/“then”/“else”
  • 根据核心规范将关键字分类为断言或注释
  • 警告将来可能会删除“dependencies”
  • 为了可读性,将验证关键字分组到子部分
  • 将“readOnly”从超模式移动到验证元数据
  • 添加了“writeOnly”
  • 添加了字符串编码的媒体部分,包含以前的超模式“media”关键字
  • 恢复了“regex”格式(删除是无意的)
  • 添加了“date”和“time”格式,并保留了其他 RFC 3339 格式名称
  • I18N 格式:“iri”、 “iri-reference”、 “idn-hostname”、 “idn-email”
  • 澄清“json-pointer”格式是指字符串编码,而不是 URI 片段
  • 修复了将“minimum”和“exclusiveMinimum”含义颠倒的拼写错误
  • 将格式语法引用移至规范性引用
  • JSON 是规范性要求
draft-wright-json-schema-validation-01
  • 将格式名称标准化为带连字符的完整单词(“uriref”变为“uri-reference”)
  • 添加格式“uri-template”和“json-pointer”
  • 将“exclusiveMaximum”/“exclusiveMinimum”从“maximum”/“minimum”的布尔修饰符更改为独立的数字字段。
  • 将 additionalItems/items 分成两个部分
  • 重新设计了 properties/patternProperties/additionalProperties 定义
  • 添加了“examples”关键字
  • 添加了“contains”关键字
  • 允许空的“required”和“dependencies”数组
  • 修复了“type”对原始类型的引用
  • 添加了“const”关键字
  • 添加了“propertyNames”关键字
draft-wright-json-schema-validation-00
  • 添加了额外的安全注意事项
  • 删除了对“最新版本”元模式的引用,改为使用编号版本
  • 为简明扼要,改写了许多关键字定义
  • 添加了“uriref”格式,该格式也允许相对 URI 引用
draft-fge-json-schema-validation-00
  • 初始草案。
  • 从草案 v3 中抢救。
  • 重新定义“required”关键字。
  • 删除“extends”、 “disallow”
  • 添加“anyOf”、 “allOf”、 “oneOf”、 “not”、 “definitions”、 “minProperties”、 “maxProperties”。
  • “dependencies”成员值不再可以是单个字符串;属性依赖数组中至少需要一个元素。
  • 将“divisibleBy”重命名为“multipleOf”。
  • “type”数组不再可以包含模式;删除“any”作为可能的值。
  • 重新设计“format”部分;使支持可选。
  • “format”:删除属性“phone”、 “style”、 “color”;将“ip-address”重命名为“ipv4”;为所有属性添加引用。
  • 提供算法来计算数组/对象实例的模式。
  • 添加互操作性注意事项。

作者地址

奥斯汀·赖特(编辑
亨利·安德鲁斯(编辑
本·哈顿(编辑
Postman