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

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 为:

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

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

6.1.1. type

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

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

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

6.1.2. enum

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

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

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

6.1.3. const

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

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

当实例的值等于关键字的值时,实例成功验证此关键字。

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

6.2.1. multipleOf

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

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

6.2.2. maximum

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

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

6.2.3. exclusiveMaximum

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

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

6.2.4. minimum

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

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

6.2.5. exclusiveMinimum

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

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

6.3. 字符串的验证关键字

6.3.1. maxLength

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

当字符串实例的长度小于或等于此关键字的值时,它相对于此关键字有效。

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

6.3.2. minLength

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

当字符串实例的长度大于或等于此关键字的值时,它相对于此关键字有效。

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

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

6.3.3. pattern

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

当正则表达式成功匹配实例时,字符串实例被认为有效。回顾:正则表达式不会隐式锚定。

6.4. 数组的验证关键字

6.4.1. maxItems

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

当数组实例的大小小于或等于此关键字的值时,它相对于“maxItems”有效。

6.4.2. minItems

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

当数组实例的大小大于或等于此关键字的值时,它相对于“minItems”有效。

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

6.4.3. uniqueItems

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

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

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

6.4.4. maxContains

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

如果 "contains" 不存在于同一个 schema 对象中,那么该关键字将无效。

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

6.4.5. minContains

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

如果 "contains" 不存在于同一个 schema 对象中,那么该关键字将无效。

实例数组根据 "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" 注释关键字的定义是为了允许 schema 作者传递有关值的固定子集的语义信息,这些值由权威资源(无论是 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" 的值作为注释。这使应用程序级验证在 schema 验证不可用或不足时可用。

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

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

  • 应该为下面定义的每个格式属性提供实现特定的尽力而为的验证;
  • 可以选择实现任何或所有格式属性的验证为无操作,通过始终生成真值验证结果;

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

7.2.2. 格式断言词汇表

当格式断言词汇表用真值声明时,实现必须提供对该规范定义的所有格式的完整验证支持。无法提供完整验证支持的实现必须拒绝处理 schema。

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

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

对格式属性进行最小验证的要求是有意模糊和宽松的,因为许多属性的复杂性。尤其要注意,此要求仅限于语法检查;不应期望实现会发送电子邮件,尝试连接到 URL,或以其他方式检查格式实例标识的实体的存在。 预期的是,对于像日期时间这样的简单格式,语法验证将是彻底的。对于像电子邮件地址这样复杂的格式,它是各种标准的混合体,随着时间的推移进行了无数的调整,以及可能受到使用该值的其他应用程序限制的模糊或过时的规则,最小验证就足够了。例如,不包含 "@" 的实例字符串显然不是有效的电子邮件地址,同样,包含 7 位 ASCII 之外的字符的 "email" 或 "hostname" 显然无效。

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

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

7.2.3. 自定义格式属性

实现 MAY 支持自定义格式属性。除了各方之间的协议外,模式作者 SHALL NOT 预期对等实现支持此类自定义格式属性。实现 MUST NOT 无法将未知格式收集为注释。当指定 Format-Assertion 词汇表时,实现 MUST 在遇到未知格式时失败。

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

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

7.3.2. 电子邮件地址

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

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

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

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

7.3.3. 主机名

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

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

hostname
RFC 1123,第 2.1 节 [RFC1123] 所定义,包括使用 RFC 5891,第 4.4 节 [RFC5891] 中指定的 Punycode 算法生成的主机名。
idn-hostname
如 RFC 1123 中针对 hostname 所定义,或者如 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
如果字符串实例是根据 [RFC3986] 的有效 URI,则它对该属性有效。
uri-reference
如果字符串实例是根据 [RFC3986] 的有效 URI 引用(URI 或相对引用),则它对该属性有效。
iri
如果字符串实例是根据 [RFC3987] 的有效 IRI,则它对该属性有效。
iri-reference
如果字符串实例是根据 [RFC3987] 的有效 IRI 引用(IRI 或相对引用),则它对该属性有效。
uuid
如果字符串实例是根据 [RFC4122] 的 UUID 的有效字符串表示,则它对该属性有效。

请注意,所有有效的 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

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

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

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

7.3.7. JSON 指针

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

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

为了允许绝对和相对 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 一样。

此词汇表(称为 Content 词汇表)的当前 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 默认情况下自动解码、解析和/或验证字符串内容。这也支持将嵌入式文档用于与处理包含文档的消费者不同的消费者进行处理的用例。

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

实现可以提供自动解码、解析和/或验证字符串内容的功能。但是,**不能**默认执行这些操作,**必须**分别提供每个字符串编码文档的验证结果,与包含文档分开。此过程**应该**等同于根据原始模式完全评估实例,然后使用注释解码、解析和/或验证每个字符串编码文档。 截至目前,自动解码、解析和验证功能的解析数据和/或验证结果的执行和返回的确切机制尚未确定。如果此功能得到普及,未来草案中可能会更详细地规定。

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

8.3. contentEncoding

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

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

由于“base64”在两个 RFC 中都有定义,因此**应该**假设来自 RFC 4648 的定义,除非字符串专门用于 MIME 上下文。请注意,所有这些编码都会导致字符串仅包含 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”将用于将密码输入字段标记为只读。

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

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

9.5. "examples"

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

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

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

10. 安全注意事项

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

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

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

处理媒体类型或编码受该媒体类型或编码的安全性考虑因素的影响。例如,RFC 4329 脚本媒体类型 [RFC4329] 中的安全性考虑因素适用于处理 JSON 字符串中编码的 JavaScript 或 ECMAScript。

11. 参考资料

11.1. 规范性引用

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

11.2. 信息性引用

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

附录 A. 从验证迁移到核心中的关键词

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

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

附录 B. 致谢

感谢 Gary Court、Francis Galiegue、Kris Zyp 和 Geraint Luff 对 JSON 模式早期草案的贡献。

感谢 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" 作为可能的 value 删除。
  • 重新编写 "format" 部分;使支持成为可选。
  • "format": 删除属性 "phone"、"style"、"color";将 "ip-address" 重命名为 "ipv4";添加所有属性的引用。
  • 提供算法来计算数组/对象实例的模式。
  • 添加互操作性注意事项。

作者地址

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