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

JSON Schema 验证:用于 JSON 结构验证的词汇表

摘要

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

致读者的说明

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

如需更多信息,请参见 https://json-schema.org/

如需提供反馈,请使用此问题跟踪器、主页上列出的通信方式,或向文档编者发送电子邮件。

本备忘录状态

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

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

互联网草案是最长有效期为六个月的草案文档,并且可以在任何 时间被其他文档更新、替换或废弃。将互联网草案用作参考 材料,或以“进行中的工作”之外的方式引用它们,都是不合适的。

本互联网草案将于 2022 年 12 月 18 日过期。

目录

1. 引言

JSON Schema 可用于要求给定的 JSON 文档(一个实例) 满足一定数量的准则。这些准则通过使用 本规范中描述的关键字来断言。此外,还定义了一组关键字, 用于辅助交互式用户界面实例生成。

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

2. 约定与术语

本文档中的关键字 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、 "SHOULD NOT"、"RECOMMENDED"、"MAY" 和 "OPTIONAL" 应按 RFC 2119 [RFC2119] 中所述进行解释。

本规范使用术语 "container instance" 来同时指数组和 对象实例。它使用术语 "children instances" 来指数组元素 或对象成员值。

如果数组值中的元素没有两个元素 相等 [json-schema],则称这些元素是唯一的。

3. 概述

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

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

本规范定义了一组断言关键字,以及一小组 可用于用有用信息注解 JSON 实例的元数据关键字。 第 7 节关键字主要意图 作为注解,但也可以可选地用作断言。 第 8 节关键字是用于处理 作为 JSON 字符串嵌入的文档的注解。

4. 互操作性注意事项

4.1. 字符串 实例的验证

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

4.2. 数值 实例的验证

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

4.3. 正则表达式

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

5. 元模式

默认 JSON Schema 方言元模式的当前 URI 是 https://json-schema.org/draft/2020-12/schema。 为方便模式作者,此元模式描述了一种方言, 其由本规范和 JSON Schema Core 规范中 定义的所有词汇表组成, 并包括两个在过渡期内保留的旧关键字。 各个词汇表和词汇表元模式 URI 在 以下每一节中给出。某些词汇表是可选支持的, 这会在相关章节中详细说明。

为了更正错误,可以在规范草案之间发布 更新后的词汇表和元模式 URI。实现 应将日期晚于本规范草案且 早于下一份草案的 URI 视为表示 与此处所列相同的语法和语义。

6. 结构验证词汇表

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

不使用 "$vocabulary" 的元模式应被视为 需要此词汇表,就好像其 URI 以 true 值存在一样。

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

对应元模式的当前 URI 是: https://json-schema.org/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" 不存在于同一模式对象内, 则此关键字没有效果。

实例数组针对 "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 还是其他外部 规范。

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

此词汇表的当前 URI(称为 Format-Annotation 词汇表)是: <https://json-schema.org/draft/2020-12/vocab/format-annotation>。对应 元模式的当前 URI 是: https://json-schema.org/draft/2020-12/meta/format-annotation。 实现必须支持此词汇表。

除 Format-Annotation 词汇表之外,还提供了一个次级词汇表, 用于自定义元模式,它将 "format" 定义为断言。 Format-Assertion 词汇表的 URI 是: <https://json-schema.org/draft/2020-12/vocab/format-assertion>。对应 元模式的当前 URI 是: https://json-schema.org/draft/2020-12/meta/format-assertion。 实现对 Format-Assertion 词汇表的支持是可选的。

同时指定 Format-Annotation 和 Format-Assertion 词汇表在功能上 等价于仅指定 Format-Assertion 词汇表,因为其要求 是 Format-Annotation 词汇表的超集。

7.2. 实现 要求

"format" 关键字按所引用词汇表的定义发挥作用。

7.2.1. Format-Annotation 词汇表

如果实现支持注解收集,则 format 的值必须作为注解被收集。 当模式验证不可用或不充分时,这会启用应用级 验证。

实现仍可以将 "format" 作为断言以及注解处理,并尝试 验证该值是否符合指定语义。实现必须提供选项以启用 和禁用此类求值,并且默认必须禁用。实现应记录 它们对此类验证的支持级别。 指定 Format-Annotation 词汇表并在实现中启用验证 不应被视为等价于指定 Format-Assertion 词汇表,因为当未指定 Format-Assertion 词汇表时,并不要求实现 提供完整的验证支持。

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

  • 应为以下定义的每个 format 属性提供 实现特定的尽力而为验证;
  • 可以选择将任意或所有 format 属性的验证实现为 no-op,即始终产生 true 的验证结果;

这与实现的当前现实相符:实现为部分或全部 format 属性提供的验证级别差异很大, 甚至完全不验证。它也被设计为鼓励 仅依赖注解行为,并在应用中执行语义 验证,这是推荐的最佳实践。

7.2.2. Format-Assertion 词汇表

当 Format-Assertion 词汇表以 true 值声明时, 实现必须为本规范定义的所有格式 提供完整的验证支持。无法提供完整 验证支持的实现必须拒绝处理该模式。

支持 Format-Assertion 词汇表的实现:

  • 如果实现支持注解收集,仍必须将 "format" 作为注解收集;
  • 必须将 "format" 作为断言求值;
  • 必须为本规范中定义的所有 format 属性, 以及它识别的任何额外 format 属性,实现语法验证, 使得存在正确类型的可能实例值 会验证失败。

format 属性的最低验证要求有意保持 模糊且宽松,这是由于许多属性涉及的复杂性。 特别注意,该要求仅限于语法检查;不应 期望实现会发送电子邮件、尝试连接 到 URL,或以其他方式检查由 format 实例 标识的实体是否存在。 期望是,对于 date-time 等简单格式,语法 验证将较为彻底。对于电子邮件地址等复杂格式, 它们是各种标准和随时间发生的大量调整的混合体, 带有晦涩和/或废弃的规则,这些规则可能会也可能不会 受到使用该值的其他应用限制,因此最低限度的验证 已足够。例如,不包含 "@" 的实例字符串显然不是 有效的电子邮件地址,而包含 7 位 ASCII 之外字符的 "email" 或 "hostname" 同样显然无效。

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

标准核心和验证元模式第 5 节 在其 "$vocabulary" 关键字中以 false 值包含此词汇表, 因为默认情况下,不要求实现支持此关键字 作为断言。以 true 值支持 format 词汇表 被认为会显著增加代码大小,并在某些情况下增加执行时间, 因而并不适合所有实现。

7.2.3. 自定义 format 属性

实现可以支持自定义 format 属性。除非各方达成协议, 否则模式作者不应期望对等实现支持此类 自定义 format 属性。实现不得因收集未知格式 作为注解而失败。当指定 Format-Assertion 词汇表时, 实现在遇到未知格式时必须失败。

词汇表不支持为关键字专门声明不同的值集合。 由于此限制,以及此关键字历史上不均衡的实现情况, 如果需要互操作性,建议在自定义词汇表中定义 额外关键字,而不是额外的 format 属性。

7.3. 已定义格式

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

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

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

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

date-time:
如果字符串实例是按照 "date-time' ABNF 规则(上文引用)给出的有效表示, 则该字符串实例针对该属性有效
date:
如果字符串实例是按照 "full-date" ABNF 规则(上文引用)给出的有效表示, 则该字符串实例针对该属性有效
time:
如果字符串实例是按照 "full-time" ABNF 规则(上文引用)给出的有效表示, 则该字符串实例针对该属性有效
duration:
如果字符串实例是按照 "duration" ABNF 规则(上文引用)给出的有效表示, 则该字符串实例针对该属性有效

实现可以使用该 RFC 中任意位置定义的其他 格式名称来支持额外属性。如果实现了 "full-date" 或 "full-time", 则必须实现对应的短形式(分别为 "date" 或 "time"), 并且其行为必须相同。实现不应定义 名称匹配 RFC 3339 格式的扩展属性,除非它按照 该格式的规则进行验证。 当前对于是否需要支持所有 RFC 3339 格式尚无共识, 因此这种保留命名空间的方法将鼓励实验, 而不承诺整个集合。要么 format 实现要求 在整体上会变得更灵活,要么这些属性很可能 会被提升为完全指定的属性,或被移除。

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:
如 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:
如果字符串实例是根据 [RFC3986] 的 有效 URI,则它针对该属性有效。
uri-reference:
如果字符串实例是根据 [RFC3986] 的有效 URI Reference(URI 或 relative-reference), 则它针对该属性有效。
iri:
如果字符串实例是根据 [RFC3987] 的 有效 IRI,则它针对该属性有效。
iri-reference:
如果字符串实例是根据 [RFC3987] 的有效 IRI Reference(IRI 或 relative-reference), 则它针对该属性有效。
uuid:
如果字符串实例是根据 [RFC4122] 的有效 UUID 字符串表示,则它针对该属性有效。

注意,所有有效 URI 都是有效 IRI,所有有效 URI References 也都是有效 IRI References。

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

7.3.6. uri-template

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

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

注意,URI Templates 可用于 IRI;不存在单独的 IRI Template 规范。

7.3.7. JSON Pointers

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

json-pointer:
如果字符串实例是 JSON Pointer 的有效 JSON 字符串表示, 如 RFC 6901,第 5 节 [RFC6901] 所定义,则它针对该属性有效。
relative-json-pointer:
如果字符串实例是有效的 Relative JSON Pointer [relative-json-pointer],则它针对该属性有效。

为了同时允许绝对和相对 JSON Pointers,请使用 "anyOf" 或 "oneOf" 来指示对任一格式的支持。

7.3.8. regex

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

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

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

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

8.1. 前言

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

这些属性提供了解释 JSON 数据为富媒体文档所需的额外信息。 它们描述内容的类型、其编码方式, 以及/或者其可能如何被验证。它们不作为验证断言; 格式错误的字符串编码文档不得导致包含它的实例 被视为无效。

不使用 "$vocabulary" 的元模式应被视为 需要此词汇表,就好像其 URI 以 true 值存在一样。

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

对应元模式的当前 URI 是: https://json-schema.org/draft/2020-12/meta/content

8.2. 实现 要求

由于安全和性能方面的考虑,以及可能内容类型的开放性, 实现默认不得自动解码、解析, 以及/或者验证字符串内容。这还支持 嵌入式文档的用例:这些文档意图由不同于 处理包含文档的消费者来处理。

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

实现可以提供自动解码、解析,以及/或者验证 字符串内容的能力。但是,它默认不得执行这些 操作,并且必须将每个字符串编码文档的验证结果 与外层文档分开提供。此过程应等价于 先根据原始模式完整求值实例, 然后使用注解来解码、解析, 以及/或者验证每个字符串编码文档。 目前,从这种自动解码、解析和验证功能中 执行并返回已解析数据以及/或者验证结果的确切机制 暂未指定。如果此类功能被证明很受欢迎, 它可能会在未来草案中更完整地指定。

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

8.3. contentEncoding

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

RFC 4648 [RFC4648] 中列出了表示 base 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",则这 表示编码是 identity encoding,即 为了在 UTF-8 字符串中表示该内容, 不需要任何转换。

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

8.4. contentMediaType

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

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

8.5. contentSchema

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

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

此属性的值必须是有效的 JSON schema。如果 "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(称为 Meta-Data 词汇表)是: <https://json-schema.org/draft/2020-12/vocab/meta-data>。

对应元模式的当前 URI 是: https://json-schema.org/draft/2020-12/meta/meta-data

9.1. "title" 和 "description"

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

这两个关键字都可用于以 关于此用户界面生成的数据的信息来装饰用户界面。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 Scripting Media Types [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. and N. Borenstein, "多用途互联网邮件扩展(MIME)第一部分:互联网 消息正文格式", RFC 2045, DOI 10.17487/RFC2045, , <https://www.rfc-editor.org/info/rfc2045>.
[RFC2046]
Freed, N. and 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. and C. Newman, "互联网上的日期和时间:时间戳", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/info/rfc3339>.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "统一资源标识符 (URI):通用语法", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>.
[RFC3987]
Duerst, M. and M. Suignard, "国际化资源标识符(IRI)", RFC 3987, DOI 10.17487/RFC3987, , <https://www.rfc-editor.org/info/rfc3987>.
[RFC4122]
Leach, P., Mealling, M., and R. Salz, "通用唯一标识符(UUID) URN 命名空间", RFC 4122, DOI 10.17487/RFC4122, , <https://www.rfc-editor.org/info/rfc4122>.
[RFC4291]
Hinden, R. and S. Deering, "IP 版本 6 地址架构", 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., and D. Orchard, "URI Template", RFC 6570, DOI 10.17487/RFC6570, , <https://www.rfc-editor.org/info/rfc6570>.
[RFC6531]
Yao, J. and W. Mao, "国际化电子邮件的 SMTP 扩展", RFC 6531, DOI 10.17487/RFC6531, , <https://www.rfc-editor.org/info/rfc6531>.
[RFC6901]
Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., "JavaScript Object Notation (JSON)Pointer", RFC 6901, DOI 10.17487/RFC6901, , <https://www.rfc-editor.org/info/rfc6901>.
[RFC8259]
Bray, T., Ed., "JavaScript Object Notation (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., and B. Hutton, Ed., "Relative JSON Pointers", 进行中的工作, 互联网草案, 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., and 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. 从 Validation 移至 Core 的关键字

自此草案起,若干关键字已从本文档移至 Core 规范 [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"
此关键字曾有两种不同的行为模式,这使得它 相对难以实现和推理。 模式形式已移至 Core,并作为 applicator 词汇表的一部分 重命名为 "dependentSchemas"。 它类似于 "properties",不同之处在于它不是将 子模式应用于属性值,而是将其应用于包含该属性的 对象。 属性名数组形式保留在此处,并重命名为 "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 rule"
draft-bhutton-json-schema-validation-00
  • 将 email format RFC 引用更正为 5321,而不是 5322
  • 澄清 "contentEncoding" 值的集合和含义
  • 引用 ECMA-262 第 11 版作为正则表达式 支持依据
  • 将 "format" 拆分为仅注解词汇表和 断言词汇表
  • 澄清 "deprecated" 适用于数组时的情况
draft-handrews-json-schema-validation-02
  • 将关键字分组为正式词汇表
  • 根据词汇表更新 "format" 实现要求
  • 默认情况下,不得验证 "format",但可以启用 验证
  • 可使用词汇表声明来要求 "format" 验证
  • 将 "definitions" 作为 "$defs" 移至核心规范
  • 将 applicator 关键字移至核心规范
  • 将 "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" 从 hyper-schema 移至验证 元数据
  • 添加 "writeOnly"
  • 添加字符串编码媒体章节,以及原 hyper-schema "media" 关键字
  • 恢复 "regex" 格式(移除是无意的)
  • 添加 "date" 和 "time" 格式,并保留额外的 RFC 3339 格式名称
  • I18N 格式:"iri"、"iri-reference"、"idn-hostname"、 "idn-email"
  • 澄清 "json-pointer" 格式表示字符串 编码,而不是 URI 片段
  • 修复颠倒 "minimum" 和 "exclusiveMinimum" 含义的拼写错误
  • 将 format 语法引用移入规范性 参考文献
  • 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
  • 添加额外的安全注意事项
  • 移除对 "latest version" 元模式的引用,改用 编号版本
  • 为简洁起见重述许多关键字定义
  • 添加也允许相对 URI 引用的 "uriref" 格式
draft-fge-json-schema-validation-00
  • 初始草案。
  • 从 draft v3 中抢救而来。
  • 重新定义 "required" 关键字。
  • 移除 "extends"、"disallow"
  • 添加 "anyOf"、"allOf"、"oneOf"、"not"、"definitions"、 "minProperties"、 "maxProperties"。
  • "dependencies" 成员值不再可以是单个 字符串;属性依赖数组中 至少需要一个元素。
  • 将 "divisibleBy" 重命名为 "multipleOf"。
  • "type" 数组不再可以包含模式;移除 "any" 作为可能 值。
  • 重写 "format" 章节;使支持成为可选。
  • "format":移除属性 "phone"、"style"、"color"; 将 "ip-address" 重命名为 "ipv4";为所有属性添加引用。
  • 提供算法以计算 array/object 实例的模式。
  • 添加互操作性注意事项。

作者地址

Austin Wright(编者
Henry Andrews(编者
Ben Hutton(编者
Postman