| 互联网草案 | JSON Schema | 2022 年 6 月 |
| Wright 等 | 2022 年 12 月 18 日到期 | [页] |
JSON Schema 定义了媒体类型 "application/schema+json",这是一种基于 JSON 的格式, 用于描述 JSON 数据的结构。 JSON Schema 断言一个 JSON 文档必须呈现的样子、 从中提取信息的方式, 以及如何与其交互。 "application/schema-instance+json" 媒体类型提供了额外的、 功能丰富的与 "application/schema+json" 的集成,超出了 "application/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 日到期。¶
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
JSON Schema 是一种用于定义 JSON 数据结构的 JSON 媒体类型。JSON Schema 旨在定义 JSON 数据的验证、文档化、超链接导航和交互 控制。¶
本规范定义 JSON Schema 的核心术语和机制,包括 通过引用指向另一个 JSON Schema、 解引用 JSON Schema 引用、 指定所使用的方言、 指定某个方言的词汇表要求, 以及定义预期输出。¶
其他规范定义用于执行验证、 链接、注解、导航和交互断言的词汇表。¶
本文档中的关键词 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、 "SHOULD NOT"、"RECOMMENDED"、"MAY" 和 "OPTIONAL" 应按 RFC 2119 [RFC2119] 中的描述进行 解释。¶
本文档中的术语 "JSON"、"JSON text"、"JSON value"、"member"、"element"、"object"、"array"、 "number"、"string"、"boolean"、"true"、"false" 和 "null" 应按 RFC 8259 [RFC8259] 中的定义进行解释。¶
本文档提出一种新的媒体类型 "application/schema+json",用于标识描述 JSON 数据的 JSON Schema。 它还提出了另一个可选媒体类型 "application/schema-instance+json", 用于提供额外的集成功能。 JSON Schema 本身就是 JSON 文档。 本规范及相关规范定义了一些关键字,使作者能够以多种方式描述 JSON 数据。¶
JSON Schema 使用关键字对 JSON 实例断言约束,或为这些 实例附加额外信息。其他关键字用于将 断言和注解应用到更复杂的 JSON 数据结构,或基于 某种条件进行应用。¶
为了便于复用,关键字可以组织成词汇表。一个词汇表 由一组关键字及其语法和语义组成。 方言被定义为一组词汇表及其必需支持, 并在元模式中标识。¶
JSON Schema 可以通过定义额外的词汇表来扩展, 也可以不那么正式地通过在任何词汇表之外定义额外关键字来扩展。 未识别的单个关键字只会将其值收集为注解, 而对于未识别词汇表的行为,可以在声明正在使用哪些词汇表时 进行控制。¶
本文档定义了一个核心词汇表,任何实现都 MUST 支持它, 并且不能禁用它。其每个关键字都以 "$" 字符为前缀, 以强调其必需性质。该词汇表对于 "application/schema+json" 媒体 类型的功能至关重要,并用于引导加载其他词汇表。¶
此外,本文档定义了一个 RECOMMENDED 的关键字词汇表, 用于有条件地应用子模式,以及将子模式应用于 对象和数组的内容。要为非平凡的 JSON 实例编写模式, 无论这些模式是用于断言验证、注解, 还是二者兼有,都需要此词汇表或与其非常相似的词汇表。 虽然它不是必需核心词汇表的一部分,但为了获得最大的 互操作性,本文档包含了这个额外词汇表, 并强烈鼓励使用它。¶
用于结构验证或超媒体注解等目的的其他词汇表 在其他文档中定义。这些其他文档各自定义了一个方言, 收集为该文档目的编写模式所需的标准词汇表集合。¶
JSON 文档是由 application/json 媒体类型描述的信息资源 (一系列八位字节)。¶
在 JSON Schema 中,术语 "JSON document"、"JSON text" 和 "JSON value" 因其定义的数据模型而可以互换使用。¶
JSON Schema 仅针对 JSON 文档定义。不过,任何能够被解析为 JSON Schema 数据模型或按该数据模型处理的文档或内存 结构,都可以相对于 JSON Schema 进行解释,包括像 CBOR [RFC7049] 这样的媒体类型。¶
应用某个模式的 JSON 文档称为一个“实例”。¶
JSON Schema 定义于 "application/json" 或兼容文档之上, 包括带有 "+json" 结构化语法后缀的媒体类型。¶
在这些媒体类型中,本规范定义了 "application/schema-instance+json" 媒体类型,该类型定义 URI 中片段的处理方式。¶
JSON Schema 按照一种数据模型解释文档。按照该数据模型解释的 JSON 值称为一个“实例”。¶
一个实例具有六种基本类型之一,并且根据类型具有一系列可能的值:¶
因此,空白和格式化方面的考量,包括在数据模型中相等的数字所具有的不同词法 表示,均超出 JSON Schema 的范围。希望 处理这类词法表示差异的 JSON Schema 词汇表(第 8.1 节) SHOULD 定义关键字,以便在数据模型内精确解释格式化字符串, 而不是依赖原始 JSON 表示中的 Unicode 字符可用。¶
由于一个对象不能有两个具有相同键的属性, 因此对于试图在单个对象中定义两个具有 相同键的属性的 JSON 文档,其行为未定义。¶
注意,JSON Schema 词汇表可以自由定义自己的扩展 类型系统。这不应与此处定义的核心数据模型类型 混淆。例如,对于词汇表而言,"integer" 是一个合理的类型, 可定义为某个关键字的值,但数据模型 不区分整数和其他数字。¶
当且仅当两个 JSON 实例具有相同类型,并且根据数据模型具有相同值时, 称它们相等。具体而言,这意味着:¶
此定义隐含着:数组长度必须相同, 对象必须具有相同数量的成员, 对象中的属性是无序的, 无法定义多个具有相同键的属性, 并且单纯的格式差异(缩进、逗号位置、尾随 零)并不重要。¶
可以将 JSON Schema 用于 JSON Schema 数据模型的超集, 其中实例可能位于六种 JSON 数据类型之外。¶
在这种情况下,注解仍然适用;但大多数验证关键字将不再有用, 因为它们要么总是通过,要么总是失败。¶
自定义词汇表可以定义对核心数据模型超集的支持。 模式本身可能只能在该超集中表达; 例如,为了使用 "const" 关键字。¶
JSON Schema 文档,或简称为模式,是用于描述 一个实例的 JSON 文档。 模式本身可以被解释为一个实例,但 SHOULD 始终赋予 "application/schema+json" 媒体类型,而不是 "application/schema-instance+json"。"application/schema+json" 媒体 类型被定义为提供 "application/schema-instance+json" 所提供的 片段标识符语法和语义的超集。¶
JSON Schema MUST 是对象或布尔值。¶
应用于实例的对象属性称为关键字, 或模式关键字。概括地说,关键字可分为五 类:¶
关键字可以归入多个类别,不过应用器 SHOULD 只根据其子模式的结果产生断言结果。 它们不应定义独立于其子模式的额外约束。¶
同一模式对象内作为属性的关键字被称为相邻 关键字。¶
扩展关键字,即在本文档及其配套文档之外定义的关键字, 也可以自由定义其他行为。¶
JSON Schema MAY 包含不是模式关键字的属性。 未知关键字 SHOULD 被视为注解,其中关键字的值 就是注解的值。¶
空模式是没有属性,或仅有未知 属性的 JSON Schema。¶
布尔模式值 "true" 和 "false" 是平凡模式, 无论实例值如何,都会始终产生其自身作为断言结果。 它们从不产生注解结果。¶
这些布尔模式的存在是为了明确模式作者的意图, 并促进模式处理优化。它们的行为与以下模式对象完全相同 (其中 "not" 是本文档中定义的 子模式应用词汇表的一部分)。¶
虽然空模式对象是明确无歧义的,但 "false" 模式有许多 可能的等价形式。使用布尔值可以确保 人类读者和实现都能清楚理解其意图。¶
模式词汇表,或简称词汇表,是一组关键字、 它们的语法和语义。词汇表通常围绕 特定目的组织。JSON Schema 的不同用途, 如验证、超媒体或用户界面生成,将 涉及不同的词汇表集合。¶
词汇表是 JSON Schema 中主要的复用单位,因为模式 作者可以指明为了处理该模式需要哪些词汇表, 哪些是必需的或可选的。由于词汇表在元模式中由 URI 标识,通用实现可以加载扩展以支持 以前未知的词汇表。虽然关键字可以在任何 词汇表之外得到支持,但没有类似的机制来指明单个 关键字的使用。¶
模式词汇表可以由从非正式描述 到标准提案的任何形式定义,具体取决于受众和互操作性 预期。特别是,为了便于非公开组织内部 使用词汇表,词汇表规范不必发布到 其使用范围之外。¶
自身描述模式的模式称为元模式。 元模式用于验证 JSON Schema,并指定它们 正在使用哪些词汇表。¶
通常,元模式会指定一组词汇表,并验证 符合这些词汇表语法的模式。不过,元模式 和词汇表是分离的,以便允许元模式比词汇表 规范所要求的更严格或更宽松地验证 模式符合性。元模式还可以描述和验证 不属于正式词汇表的额外关键字。¶
JSON Schema 资源是一个由 规范 [RFC6596] 的 绝对 URI [RFC3986] 标识的模式。模式资源 MAY 也可由 URI 标识,包括带有片段的 URI, 前提是得到的次级资源(如 RFC 3986 第 3.5 节 [RFC3986] 所定义)与 主资源相同。这可能发生在空片段, 或一个模式资源嵌入另一个资源时。任何这类带片段的 URI 都被视为非规范 URI。¶
根模式是构成所讨论整个 JSON 文档的模式。 根模式始终是一个模式资源,其中 URI 按第 9.1.1 节所述确定。 注意,将模式嵌入另一种格式的文档并不具有 此意义上的根模式资源。此类用法究竟如何 与 JSON Schema 文档和资源概念相契合, 将在未来草案中澄清。 ¶
一些关键字本身接受模式,从而允许 JSON Schema 嵌套:¶
{
"title": "root",
"items": {
"title": "array item"
}
}
¶
在此示例文档中,标题为 "array item" 的模式是子模式, 标题为 "root" 的模式是根模式。¶
与根模式一样,子模式也是对象或布尔值。¶
如第 8.2.1 节所讨论的,JSON Schema 文档 可以包含多个 JSON Schema 资源。在未加限定使用时, 术语“根模式”指文档的根模式。在某些 情况下,会讨论资源根模式。资源的根模式 是其顶级模式对象;如果该资源被提取为一个独立的 JSON Schema 文档,它也将是文档根模式。¶
无论多个模式资源是被嵌入还是通过引用链接, 它们都以相同方式处理,并具有相同的可用行为。¶
根据 RFC 6839 第 3.1 节 [RFC6839], 为任何 +json 媒体类型指定的片段标识符语法和语义 SHOULD 与为 "application/json" 指定的相同。 (在本文档发布时,尚未为 "application/json" 定义片段标识 语法。)¶
此外,"application/schema+json" 媒体类型支持两种 片段标识符结构:普通名称和 JSON Pointer。 "application/schema-instance+json" 媒体类型支持一种 片段标识符结构:JSON Pointer。¶
将 JSON Pointer 用作 URI 片段标识符的做法在 RFC 6901 [RFC6901] 中描述。 对于支持两种片段标识符语法的 "application/schema+json", 匹配 JSON Pointer 语法的片段标识符,包括空字符串, MUST 被解释为 JSON Pointer 片段标识符。¶
根据 W3C 的 片段 标识符最佳实践 [W3C.WD-fragid-best-practices-20121025], "application/schema+json" 中的普通名称片段标识符被保留用于引用 本地命名的模式。所有不匹配 JSON Pointer 语法的 片段标识符 MUST 被解释为 普通名称片段标识符。¶
在 "application/schema+json" 文档中定义和引用普通名称 片段标识符的方式,在 "$anchor" 关键字(第 8.2.2 节) 一节中规定。¶
实例可以是 JSON [RFC8259] 所定义的任何有效 JSON 值。 JSON Schema 不对类型施加限制:JSON Schema 可以描述任何 JSON 值,例如包括 null。¶
JSON Schema 与编程语言无关,并支持数据模型中描述的完整 值范围。 但是请注意,某些语言和 JSON 解析器可能无法在内存中 表示 JSON 可描述的完整值范围。¶
关键字 MAY 使用正则表达式来表达约束,或约束 实例值必须是正则表达式。 这些正则表达式 SHOULD 按照 ECMA-262 第 21.2.1 节 [ecma262] 中描述的正则表达式 方言有效。¶
正则表达式 SHOULD 使用 "u" 标志(或等价方式)构建,以提供 Unicode 支持,或以提供 ECMA-262 所定义 Unicode 支持的方式 进行处理。¶
此外,鉴于正则表达式构造支持方面差异很大, 模式作者 SHOULD 将自己限制为以下正则表达式 标记:¶
最后,实现 MUST NOT 将正则表达式视为 已锚定,无论是在开头还是结尾。这意味着,例如, 模式 "es" 会匹配 "expression"。¶
额外的模式关键字和模式词汇表 MAY 由任何实体定义。 除非有明确约定,否则模式作者 SHALL NOT 期望这些额外关键字和词汇表得到未明确记录此类支持的 实现支持。 实现 SHOULD 将它们不支持的关键字视为注解, 其中关键字的值就是注解的值。¶
实现 MAY 提供注册或加载处理程序的能力, 用于其不直接支持的词汇表。注册和实现此类处理程序的确切机制 取决于实现。¶
JSON Schema 关键字分为若干一般行为类别。 断言用于验证实例是否满足约束,并产生 布尔结果。注解附加信息,应用可以 以其认为合适的任何方式使用这些信息。 应用器将子模式应用于实例的各个部分,并组合 它们的结果。¶
扩展关键字 SHOULD 保持在这些类别内,并记住 尤其注解具有极高的灵活性。复杂行为通常更适合 基于注解数据委托给应用处理, 而不是直接实现为模式关键字。不过,扩展 关键字 MAY 为专门目的定义其他行为。¶
根据模式求值一个实例涉及处理模式中的所有 关键字,并将其应用于实例中的适当位置。 通常,应用器关键字会被处理,直到到达一个没有 应用器(因此没有子模式)的模式对象。实例中的适当 位置会根据模式对象中的断言和 注解关键字进行求值,其结果会按照应用器规则 收集到父模式中。¶
父模式对象的求值可以在其所有 子模式都求值完成后结束,尽管在某些情况下, 求值可能会因断言结果而短路。当正在 收集注解时,由于需要检查所有子模式以进行注解收集, 包括那些不能进一步改变断言结果的子模式, 某些断言结果短路是不可能的。¶
虽然大多数 JSON Schema 关键字可以自行求值, 或最多只需要考虑同一模式对象中 相邻关键字的值或结果,但少数关键字具有更 复杂的行为。¶
关键字的词法作用域由对象和数组的嵌套 JSON 数据结构决定。最大的这类作用域 是整个模式文档。最小的作用域是一个没有 子模式的单个模式对象。¶
关键字 MAY 被定义为带有部分值,例如 URI-reference, 该值必须根据另一个值解析,例如另一个 URI-reference 或完整 URI,而该值通过 JSON 文档的词法 结构找到。"$id"、"$ref" 和 "$dynamicRef" 核心关键字,以及 "base" JSON Hyper-Schema 关键字,都是此类行为的示例。¶
注意,某些关键字,如 "$schema",适用于整个模式资源的词法 作用域,因此 MUST 只 出现在模式资源的根模式中。¶
其他关键字可能会考虑在模式求值期间 存在的动态作用域,通常与实例文档一起考虑。 最外层的动态作用域是 处理开始处的模式对象,即使它不是模式资源根。 从此根模式到任何特定关键字的路径(该路径 包括任何可能已解析的 "$ref" 和 "$dynamicRef" 关键字) 被视为该关键字的“验证路径”。¶
词法作用域和动态作用域会保持一致,直到遇到引用关键字。 虽然跟随引用关键字会使处理 从一个词法作用域移动到另一个不同的词法作用域, 但从动态作用域的角度看,跟随引用与下降到 作为值存在的子模式没有区别。引用另一侧的关键字 若通过动态作用域解析信息,将把引用的 起始侧视为其动态父级,而不是检查本地词法包围父级。¶
动态作用域概念主要与 "$dynamicRef" 和 "$dynamicAnchor" 一起使用,应视为高级特性, 在定义额外关键字时应谨慎使用。当报告错误和收集到的注解时, 它也会出现,因为可能会以不同动态 作用域反复访问同一词法作用域。在这种情况下, 告知用户产生错误或注解的 动态路径非常重要。¶
关键字行为 MAY 根据 子模式(第 4.3.5 节)和/或相邻关键字 (同一模式对象内的关键字)及其子模式的注解结果来定义。 此类关键字 MUST NOT 导致循环依赖。 关键字 MAY 根据同一 模式对象(第 4.3 节)中是否存在另一个关键字 来修改其行为。¶
缺失的关键字 MUST NOT 产生 false 断言结果,MUST NOT 产生注解结果,并且 MUST NOT 作为其自身行为定义的一部分 导致任何其他模式被求值。 不过,鉴于缺失关键字不会贡献注解, 缺少注解结果可能会间接改变 其他关键字的行为。¶
在某些情况下,某个关键字的缺失关键字断言行为 与某个特定值产生的行为相同,关键字定义 SHOULD 在已知时注明这些值。不过,即使产生 默认行为的值在存在时会产生注解结果, 默认行为仍然 MUST NOT 产生注解。¶
因为注解收集会在计算和内存方面增加显著成本, 实现 MAY 选择退出此功能。 根据收集注解来规定的关键字 SHOULD 在适当时描述合理的替代方法。 本文档中的 "items" 和 "additionalProperties" 关键字展示了这种 方法。¶
注意,当某个关键字不存在此类替代方法时, 不支持注解收集的实现将无法 支持这些关键字或包含它们的词汇表。¶
标识符为模式定义 URI,或影响此类 URI 在 引用(第 8.2.3 节)中的解析方式,或二者兼有。 本文档定义的核心词汇表定义了若干 标识关键字,其中最显著的是 "$id"。¶
规范模式 URI 在处理实例时 MUST NOT 改变,但 影响 URI-reference 解析的关键字 MAY 具有 只有在运行时才能完全确定的行为。¶
虽然可以使用自定义标识符关键字,但词汇表设计者应 注意不要破坏核心关键字的功能。例如, 本规范中的 "$dynamicAnchor" 关键字将其 URI 解析 影响限制在匹配的 "$dynamicRef" 关键字上,从而使 "$ref" 的行为不受干扰。¶
应用器允许构建比单个模式对象所能完成的更复杂的模式。 对实例针对 模式文档(第 4.3 节)的求值从将 根模式(第 4.3.5 节)应用于完整实例 文档开始。此后,称为应用器的关键字用于确定 还要应用哪些额外模式。此类模式可以就地 应用于当前位置,或应用于子位置。¶
要应用的模式可以作为构成关键字值全部或 部分的子模式存在。或者,应用器可以引用 同一模式文档中其他位置的模式,或另一个文档中的模式。 标识这些被引用模式的机制由该 关键字定义。¶
应用器关键字还定义子模式或被引用模式的 布尔 断言(第 7.6 节) 结果如何被修改和/或组合,以产生应用器的布尔结果。 应用器可以对子模式的断言结果应用任何布尔逻辑运算, 但 MUST NOT 引入它们自己的新 断言条件。¶
注解(第 7.7 节)结果会与实例位置和 模式关键字位置一起保留,以便应用可以决定如何 解释多个值。¶
如 第 7.5 节 所述,应用器关键字可以 引用要应用的模式,而不是将其作为 子模式包含在应用器的值中。在这种情况下, 正在应用的模式称为被引用模式,而 包含应用器关键字的模式称为引用模式。¶
虽然根模式和子模式是基于模式 在模式文档中位置的静态概念,但被引用和引用 模式是动态的。在根据模式求值 实例期间,不同的模式对可能处于各种被引用和引用 关系中。¶
对于某些按引用应用器,例如 "$ref"(第 8.2.3.1 节),可以通过对模式文档词法作用域的 静态分析来确定被引用模式。其他应用器, 如 "$dynamicRef"(与 "$dynamicAnchor" 一起),可能会使用动态 作用域,因此只能在使用实例求值 模式的过程中解析。¶
JSON Schema 可用于对 JSON 文档断言约束,该文档 要么通过断言,要么未通过断言。这种方法可用于验证 是否符合约束,或记录满足约束所需内容。¶
JSON Schema 实现在根据模式断言求值 实例时产生一个布尔结果。¶
实例只能未通过模式中存在的断言。¶
大多数断言只约束某个特定 基本类型内的值。当实例类型不是关键字所针对的类型时, 该实例被视为符合 该断言。¶
例如,配套 验证词汇表 [json-schema-validation] 中的 "maxLength" 关键字: 只会限制某些字符串 (过长的字符串)不能有效。如果实例是数字、 布尔值、null、数组或对象,则它对于该断言是有效的。¶
此行为允许关键字更容易与可能属于 多种基本类型的实例一起使用。配套验证 词汇表还包括一个 "type" 关键字,它可以独立地 将实例限制为一种或多种基本类型。这使得 可以简洁地表达一些用例,例如某个函数可能 返回特定长度的字符串或 null 值:¶
{
"type": ["string", "null"],
"maxLength": 255
}
¶
如果 "maxLength" 也将实例类型限制为字符串, 那么这将明显更难表达,因为 按上述方式编写的示例实际上不会允许 null 值。 除非明确另有规定,否则每个关键字都会单独求值, 因此如果 "maxLength" 将实例限制为字符串, 那么在 "type" 中包含 "null" 就不会产生任何有用效果。¶
每当实例通过包含注解的模式对象及其所有 父模式对象的验证时,JSON Schema 都可以用信息注解该实例。 该信息可以是简单值,也可以 根据实例内容计算得出。¶
注解附加到实例中的特定位置。 由于许多子模式可以应用于任何单个 位置,应用可能需要决定如何处理由 不同模式对象中的同一模式关键字附加到同一实例位置的不同 注解值。¶
与断言结果不同,注解数据可以采用多种形式, 并提供给应用按其认为合适的方式使用。JSON Schema 实现不应代表应用使用所收集的信息。¶
除非另有规定,注解关键字的值 就是该关键字的值。不过,也可能存在其他行为。 例如,JSON Hyper-Schema [json-hyper-schema] 的 "links" 关键字是一种复杂注解,它生成的值部分基于 实例数据。¶
虽然断言可以进行“短路”求值,但收集 注解要求检查所有适用于实例 位置的模式,即使它们无法改变总体断言结果。 唯一的例外是,验证失败的模式对象的 子模式 MAY 被跳过,因为失败模式的注解不会被保留。¶
注解由显式定义注解收集行为的关键字收集。 注意,布尔模式无法产生注解,因为它们不使用 关键字。¶
收集到的注解 MUST 包含以下信息:¶
应用 MAY 根据贡献该值的模式位置来决定使用多个注解值中的哪一个。 这样做旨在允许灵活使用。收集模式位置 有助于这种使用。¶
例如,考虑以下模式,它使用来自 验证规范 [json-schema-validation] 的注解和断言:¶
注意,为了清晰起见,某些行已换行。¶
{
"title": "Feature list",
"type": "array",
"prefixItems": [
{
"title": "Feature A",
"properties": {
"enabled": {
"$ref": "#/$defs/enabledToggle",
"default": true
}
}
},
{
"title": "Feature B",
"properties": {
"enabled": {
"description": "If set to null, Feature B
inherits the enabled
value from Feature A",
"$ref": "#/$defs/enabledToggle"
}
}
}
],
"$defs": {
"enabledToggle": {
"title": "Enabled",
"description": "Whether the feature is enabled (true),
disabled (false), or under
automatic control (null)",
"type": ["boolean", "null"],
"default": null
}
}
}
¶
在此示例中,Feature A 和 Feature B 都使用可复用的 "enabledToggle" 模式。该模式使用 "title"、"description" 和 "default" 注解。因此,应用必须决定如何 处理 Feature A 的额外 "default" 值,以及 Feature B 的额外 "description" 值。¶
应用程序员和模式作者需要就用法达成一致。 对于此示例,我们假设他们同意使用最 具体的 "default" 值,并静默忽略任何额外、更通用的 "default" 值。我们还假设他们 同意使用所有 "description" 文本,从最 通用的开始,到最具体的结束。这要求模式 作者编写可按这种方式组合使用的描述。¶
应用可以使用模式位置路径来确定哪些 值对应哪些位置。特性的直接 "enabled" 属性模式中的值更具体,而通过 "$ref" 引用的可复用 模式下的值更通用。模式 位置路径将显示每个值是否是跨越 "$ref" 后找到的。¶
因此,Feature A 将使用默认值 true,而 Feature B 将使用通用默认值 null。Feature A 只会 具有来自 "enabledToggle" 模式的通用描述,而 Feature B 将使用该描述,并且还会追加其本地 定义的描述,用于解释如何解释 null 值。¶
注意,其他应用也可能采取其他合理方法。 例如,应用可能会认为 "default" 出现两个不同值就是错误,而不管它们的 模式位置如何。¶
产生 false 断言结果的模式对象 MUST NOT 产生任何注解结果,无论这些注解来自其自身关键字 还是子模式中的关键字。¶
注意,整体模式结果仍可能包含从其他模式位置 收集的注解。给定此模式:¶
{
"oneOf": [
{
"title": "Integer Value",
"type": "integer"
},
{
"title": "String Value",
"type": "string"
}
]
}
¶
针对实例 "This is a string",
title 注解 "Integer Value" 会被丢弃,因为该模式对象中的 type 断言
失败。title 注解 "String Value"
会被保留,因为实例通过了字符串类型断言。¶
除了可能定义自己的注解结果外, 应用器关键字还会聚合其子模式或被引用模式中收集的 注解。¶
第四类关键字只是保留一个位置,用于容纳可复用 组件,或模式作者感兴趣但不适合 复用的数据。这些关键字不影响验证或注解结果。 它们在核心词汇表中的目的,是确保某些用途所需的位置 可用,且不会被扩展 关键字重新定义。¶
虽然这些关键字不直接影响结果,但如第 9.4.2 节所解释, 为可复用模式保留位置的未识别 扩展关键字在某些情况下可能与引用产生 不良交互。¶
虽然作为本文档或相关文档一部分定义的词汇表中 没有定义可能定位和/或加载实例数据的关键字, 但其他词汇表可能希望这样做。¶
关键字 MAY 被定义为使用 JSON Pointer 或 Relative JSON Pointer 来检查 当前求值位置之外的实例部分。¶
允许使用 Relative JSON Pointer 调整位置的关键字 SHOULD 在需要默认值时默认使用当前位置。¶
本节中声明的关键字均以 "$" 开头,构成 JSON Schema 核心词汇表。这些关键字要么是处理任何模式或元模式 所必需的,包括那些跨多个文档拆分的模式或元模式, 要么用于为需要保证互操作性的目的保留 关键字。¶
核心词汇表 MUST 始终被视为强制性词汇表,以便 引导后续词汇表的处理。使用 "$vocabulary"(第 8.1 节) 关键字 声明所使用词汇表的元模式,MUST 显式列出核心词汇表, 且其值 MUST 为 true,表示它是必需的。¶
此词汇表(且仅此词汇表)值为 false 时的行为未定义, 当 "$vocabulary" 存在但未包含核心词汇表时的行为也未定义。 不过,RECOMMENDED 实现检测这些情况并在其发生时 抛出错误。声明一个元模式可选使用 Core 是没有意义的。¶
不使用 "$vocabulary" 的元模式 MUST 被视为 要求核心词汇表,就像其 URI 以 true 值出现一样。¶
核心词汇表的当前 URI 为: <https://json-schema.org/draft/2020-12/vocab/core>。¶
对应元模式的当前 URI 为: https://json-schema.org/draft/2020-12/meta/core。¶
虽然 "$" 前缀并未正式为核心词汇表保留, 但 RECOMMENDED 扩展关键字(无论在词汇表中还是其他地方) 以 "$" 之外的字符开头,以避免未来可能发生的冲突。¶
元模式和词汇表这两个概念用于告知实现 如何解释模式。每个模式都有一个元模式,可使用 "$schema" 关键字声明。¶
元模式有两个目的:¶
元模式与词汇表分离,是为了允许 词汇表以不同方式组合,并允许元模式作者 施加额外约束,例如禁止某些关键字,或 执行异常严格的语法验证,就像在 开发和测试周期中可能做的那样。每个词汇表通常标识 一个仅由该词汇表关键字组成的元模式。¶
元模式创作是 JSON Schema 的高级用法,因此 元模式特性的设计强调灵活性而不是简单性。¶
"$schema" 关键字既用作 JSON Schema 方言标识符, 也用作某个资源的标识符;该资源本身是 JSON Schema, 描述为该特定方言编写的有效模式集合。¶
此关键字的值 MUST 是一个 URI [RFC3986] (包含 scheme),并且该 URI MUST 被规范化。 当前模式 MUST 对该 URI 标识的元模式有效。¶
如果该 URI 标识可检索资源,则该资源 SHOULD 为 "application/schema+json" 媒体类型。¶
"$schema" 关键字 SHOULD 用于文档根模式对象, 并且 MAY 用于嵌入式模式资源的根模式对象。 它 MUST NOT 出现在非资源根模式对象中。如果 文档根模式中缺失它,则结果行为由实现定义。¶
此属性的值在本文档和其他文档中以及由其他方 定义。¶
"$vocabulary" 关键字用于元模式中,以标识 可用于该元模式所描述模式的词汇表。 它还用于指示每个词汇表是必需的还是可选的, 即实现 MUST 理解必需词汇表,才能 成功处理该模式。这些信息共同构成 一个方言。实现所理解的任何词汇表 MUST 按照该词汇表中包含的语义定义一致地 处理。¶
此关键字的值 MUST 是对象。该 对象中的属性名 MUST 是 URI(包含 scheme),并且该 URI MUST 被规范化。 作为属性名出现的每个 URI 都标识一组特定的 关键字及其语义。¶
URI MAY 是 URL,但可检索资源的性质 目前未定义,并保留供未来使用。词汇表作者 MAY 使用词汇表规范的 URL,以人类可读 媒体类型(如 text/html 或 text/plain)作为词汇表 URI。 词汇表文档可能会在后续草案中添加。 目前,标识关键字集合被认为已经足够,因为这 与元模式验证一起,就是当前“词汇表” 的工作方式。任何未来的词汇表文档格式都将被规定为 JSON 文档,因此暂时使用 text/html 或其他非 JSON 格式 不会在未来产生歧义。 ¶
对象属性的值 MUST 是布尔值。 如果值为 true,则不识别 该词汇表的实现 MUST 拒绝处理任何使用 "$schema" 声明 此元模式的模式。如果值为 false,则不识别该词汇表的实现 SHOULD 继续处理 此类模式。如果实现理解该词汇表,则该值不会产生影响。¶
根据 6.5,未识别 关键字 SHOULD 被视为注解。 对于由未识别词汇表定义的关键字, 情况仍然如此。目前无法区分 未识别关键字是由词汇表定义的, 还是不属于任何词汇表。¶
"$vocabulary" 关键字 SHOULD 用于任何旨在作为元模式使用的模式 文档的根模式中。它 MUST NOT 出现在子模式中。¶
在未作为元模式处理的模式文档中, "$vocabulary" 关键字 MUST 被忽略。这允许验证 元模式 M 是否符合其自身的元模式 M',而不要求 验证器理解 M 声明的词汇表。¶
如果 "$vocabulary" 缺失,实现 MAY 根据元模式 确定行为,前提是它可从引用模式的 "$schema" 关键字的 URI 值识别该元模式。 这就是在词汇表出现之前识别行为(如 Hyper-Schema 用法)的 方式。¶
如果由模式引用的元模式未被识别, 或者缺失,则行为由实现定义。 如果实现 继续处理该模式,它 MUST 假定使用 核心词汇表。如果实现是为特定目的构建的, 那么它 SHOULD 假定使用与该目的最相关的所有词汇表。¶
例如,作为验证器的实现 SHOULD 假定使用本 规范以及配套验证规范中的所有词汇表。¶
注意,对 "$vocabulary" 的处理限制意味着 使用 "$ref" 或类似关键字引用其他元模式的 元模式,不会自动继承那些其他元模式的 词汇表声明。所有此类声明 必须在每个旨在作为元模式使用的模式文档的根中重复。 这在 示例元模式(附录 D.2) 中展示。 此要求允许实现为每个元模式 在单一位置找到所有词汇表要求信息。 由于模式可扩展性意味着存在无穷多种潜在方式 可通过引用组合更细粒度的元模式, 要求实现预判所有可能性并 在被引用元模式中搜索词汇表会 过于繁重。 ¶
更新后的词汇表和元模式 URI MAY 在 规范草案之间发布,以便纠正错误。实现 SHOULD 将日期晚于本规范草案且早于下一草案的 URI 视为指示与此处列出的相同语法和语义。¶
为了在庞大的生态系统中区分模式,模式由 URI [RFC3986] 标识,并且可以通过指定其他模式的 URI 嵌入对其他模式的引用。¶
若干关键字可以接受相对 URI-reference [RFC3986], 或用于构造相对 URI-reference 的值。对于这些关键字, 必须建立基础 URI 以解析引用。¶
"$id" 关键字使用模式资源的 规范 [RFC6596] URI 来标识该模式资源。¶
注意,该 URI 是标识符,不一定是网络定位符。 在网络可寻址 URL 的情况下,模式不必能够 从其规范 URI 下载。¶
如果存在,此关键字的值 MUST 是字符串,并且 MUST 表示 有效的 URI-reference [RFC3986]。该 URI-reference SHOULD 被规范化,并且 MUST 解析为 absolute-URI [RFC3986](不带片段), 或带空片段的 URI。¶
空片段形式 NOT RECOMMENDED,仅为向后兼容而保留, 并且因为 application/schema+json 媒体类型定义了带有 空片段的 URI 与移除片段后的同一 URI 标识相同资源。不过,由于这种等价关系并非 RFC 3986 规范化过程 [RFC3986] 的一部分, 实现者和模式作者不能依赖通用 URI 库 理解它。¶
因此,"$id" MUST NOT 包含非空片段,并且 SHOULD NOT 包含空片段。无论是否存在空片段, absolute-URI 形式 MUST 被视为 规范 URI。 当前允许空片段,是因为较旧的元模式在其 $id (或之前的 id)中包含空片段。 未来草案可能会直接禁止 "$id" 中甚至出现空片段。 ¶
absolute-URI 还作为模式资源内关键字中相对 URI-reference 的基础 URI,符合 RFC 3986 第 5.1.1 节 [RFC3986] 关于嵌入在内容中的基础 URI 的规定。¶
子模式中出现 "$id" 表明该子模式在单个模式文档中 构成一个不同的模式资源。此外, 根据 RFC 3986 第 5.1.2 节 [RFC3986] 关于封装实体的规定,如果子模式中的 "$id" 是相对 URI-reference,则解析该引用的基础 URI 是 父模式资源的 URI。¶
如果没有父模式对象使用 "$id" 显式将自身标识为资源, 则基础 URI 是整个文档的基础 URI,如 上一节(第 9.1.1 节)中给出的步骤所建立。¶
JSON Schema 文档的根模式 SHOULD 包含一个 "$id" 关键字, 其值为 absolute-URI [RFC3986](包含 scheme, 但不包含片段)。¶
使用 JSON Pointer 片段需要了解模式的结构。 在编写旨在提供可复用 模式的模式文档时,最好使用不绑定到 任何特定结构位置的普通名称片段。这样可以移动子模式, 而不需要更新 JSON Pointer 引用。¶
"$anchor" 和 "$dynamicAnchor" 关键字用于指定此类 片段。它们是标识符关键字,只能用于创建 普通名称片段,而不是像 "$id" 那样创建绝对 URI。¶
结果片段所追加到的基础 URI,是包含所讨论 "$anchor" 或 "$dynamicAnchor" 的模式资源的规范 URI。如上一节所述,这要么是同一模式对象或父模式对象中 最近的 "$id",要么是 根据 RFC 3986 确定的文档基础 URI。¶
与 URI 的通常用法分开,"$dynamicAnchor" 表明该片段在与 "$dynamicRef" 关键字一起使用时 是一个扩展点。这个低层级的高级特性 使扩展递归模式(如元模式)更容易, 而不会对该扩展施加任何特定语义。 详情见关于 "$dynamicRef"(第 8.2.3.2 节) 的章节。¶
在大多数情况下,普通片段行为既足够 又更直观。因此,RECOMMENDED 使用 "$anchor" 创建普通名称片段,除非确实明确 需要 "$dynamicAnchor"。¶
如果存在,此关键字的值 MUST 是字符串,并且 MUST 以 字母([A-Za-z])或下划线("_")开头,后跟任意数量的字母、 数字([0-9])、连字符("-")、下划线("_")和句点(".")。 这匹配 XML 的 NCName 产生式 [xml-names] 的 US-ASCII 部分。 注意,锚点字符串不包含 "#" 字符, 因为它不是 URI-reference。"$anchor": "foo" 在 URI 中使用时 会变成片段 "#foo"。完整示例见下文。 ¶
在同一资源中使用 "$anchor" 和/或 "$dynamicAnchor" 的任意组合多次指定相同片段名称的效果 未定义。实现 MAY 在检测到此类用法时抛出错误。¶
若干关键字可用于引用要应用于 当前实例位置的模式。"$ref" 和 "$dynamicRef" 是应用器 关键字,会将被引用模式应用于实例。¶
由于 "$ref" 和 "$dynamicRef" 的值是 URI References, 这提供了将模式外部化或拆分到多个文件中的可能性, 并提供了通过自引用验证递归结构的能力。¶
这些关键字产生的已解析 URI 不一定是网络 定位符,而只是标识符。如果它是网络可寻址 URL, 模式不必能够从该地址下载,并且实现 SHOULD NOT 在遇到网络可寻址 URI 时假定应执行 网络操作。¶
"$ref" 关键字是一个应用器,用于引用静态 标识的模式。其结果就是被引用模式的结果。 注意,关于结果如何确定的这一定义意味着 其他关键字可以与 "$ref" 一起出现在同一模式对象中。 ¶
"$ref" 关键字的值 MUST 是一个作为 URI-Reference 的字符串。 根据当前 URI 基础解析后,它会产生要应用模式的 URI。 此解析可在模式加载时安全执行,因为 求值实例的过程不会改变引用的解析方式。¶
"$dynamicRef" 关键字是一个应用器,允许将 完整解析推迟到运行时,此时每次在求值实例期间遇到它 都会进行解析。¶
"$dynamicRef" 与 "$dynamicAnchor" 一起实现一种协作式 扩展机制,它主要适用于递归模式 (引用自身的模式)。扩展点和 运行时确定的扩展目标都使用 "$dynamicAnchor" 定义, 并且只有在使用 "$dynamicRef" 引用时才表现出 运行时动态行为。¶
"$dynamicRef" 属性的值 MUST 是 一个 URI-Reference 字符串。根据当前 URI 基础解析后, 它会产生用作运行时解析起点的 URI。 此初始解析可在模式加载时安全执行。¶
如果初始解析得到的起点 URI 包含 由 "$dynamicAnchor" 关键字创建的片段,则初始 URI MUST 被替换为 动态作用域(第 7.1 节)中最外层模式 资源的 URI(包括片段),该资源使用 "$dynamicAnchor" 定义了同名片段。¶
否则,其行为与 "$ref" 相同,不需要运行时 解析。¶
使用这些关键字的完整示例见附录 C。 2019 年前草案中的 hyper-schema 元模式与本草案之间的差异 生动展示了这些关键字的实用性。 ¶
"$defs" 关键字为模式 作者保留一个位置,用于将可复用 JSON Schema 内联到更通用的模式中。 该关键字不直接影响验证结果。¶
此关键字的值 MUST 是对象。 该对象的每个成员值 MUST 是有效的 JSON Schema。¶
作为示例,下面是一个描述正整数数组的模式, 其中正整数约束是 "$defs" 中的子模式:¶
{
"type": "array",
"items": { "$ref": "#/$defs/positiveInteger" },
"$defs": {
"positiveInteger": {
"type": "integer",
"exclusiveMinimum": 0
}
}
}
¶
此关键字为模式作者向模式读者或维护者提供注释 保留一个位置。¶
此关键字的值 MUST 是字符串。实现 MUST NOT 向 最终用户呈现该字符串。用于编辑模式的工具 SHOULD 支持显示和 编辑此关键字。此关键字的值 MAY 用于面向使用模式的开发者的调试或错误 输出。¶
模式词汇表 SHOULD 允许在包含 词汇表关键字的任何对象中使用 "$comment"。实现 MAY 假定允许 "$comment", 除非该词汇表明确禁止它。词汇表 MUST NOT 规定 "$comment" 产生除本 规范所述之外的任何效果。¶
将其他媒体类型或编程语言 转换为 application/schema+json 或从中转换出来的工具 MAY 选择将该媒体类型或 编程语言的原生注释转换为 "$comment" 值,或从 "$comment" 值转换出来。 当原生注释和 "$comment" 属性同时存在时,此类转换的行为取决于实现。¶
实现 MAY 在处理期间的任何时刻移除 "$comment" 值。 特别是,当部署的模式大小成为问题时,这允许缩短 模式。¶
实现 MUST NOT 根据 "$comment" 属性的存在、缺失 或内容采取任何其他操作。特别是,"$comment" 的值 MUST NOT 被收集为注解结果。¶
RFC3986 第 5.1 节 [RFC3986] 定义了如何确定 文档的默认基础 URI。¶
从资料性角度看,模式的初始基础 URI 是其被找到的位置的 URI, 无论该位置是网络位置、本地文件系统,还是任何其他 可由已知 scheme 的 URI 标识的情况。¶
如果模式文档未使用 "$id" 定义显式基础 URI (嵌入在内容中),则基础 URI 按 RFC 3986 第 5 节 [RFC3986] 确定。¶
如果来源未知,或来源的 URI scheme 未知,则 MAY 使用合适的 实现特定默认 URI,如 RFC 3986 第 5.1.4 节 [RFC3986] 所述。RECOMMENDED 实现记录其假定的任何默认基础 URI。¶
如果模式对象嵌入到另一媒体类型的文档中,则 初始基础 URI 根据该 媒体类型的规则确定。¶
除非根模式中存在前文所述 "$id" 关键字, 否则此基础 URI SHOULD 被视为 模式文档根模式资源的规范 URI。¶
使用 URI 标识远程模式并不一定意味着会下载任何内容, 而是 JSON Schema 实现 SHOULD 预先了解它们将使用哪些模式, 以及标识这些模式的 URI。¶
当模式被下载时, 例如由直到运行时才知道要下载哪些模式的通用用户代理下载时, 参见 用于超媒体(第 9.5.1 节)。¶
实现 SHOULD 能够将任意 URI 与任意 模式相关联,和/或根据验证器对模式的信任程度 自动关联由模式 "$id" 给出的 URI。这些 URI 和模式 可以在处理实例之前提供给实现,或者可以 在处理模式文档时在其中记录,从而产生如附录 A 所示的关联。¶
一个模式 MAY(且很可能会)具有多个 URI,但 URI 无法 标识多个模式。当多个模式试图标识为 同一 URI 时,验证器 SHOULD 抛出错误条件。¶
如果某个模式因为被另一个 模式的 "$schema" 关键字标识为元模式而被检查, 实现 MUST 将其识别为元模式。这意味着单个模式 文档有时可能被视为普通模式, 有时又被视为元模式。¶
对于检查作为自身元模式的模式, 当实现开始将其作为普通模式处理时, 它按那些规则处理。不过,当它因检查自身 "$schema" 值 而第二次加载时,它会被视为 元模式。因此,同一文档会在一次会话过程中以两种方式处理。¶
实现 MAY 允许将某个模式显式作为元模式传入, 用于实现特定目的,例如预加载常用 元模式并预先检查其词汇表支持要求。 元模式作者 MUST NOT 期望此类特性 在实现之间具有互操作性。¶
模式可以通过赋予它们的任何 URI 来标识,包括 JSON Pointer 或由 "$id" 直接给出的 URI。在所有情况下, 解引用 "$ref" 引用都涉及首先按 RFC 3986 [RFC3986] 根据当前基础 URI 将其值解析为 URI 引用。¶
如果得到的 URI 标识当前文档中的某个模式, 或另一个已提供给实现的模式文档中的某个模式, 则该模式 SHOULD 被自动使用。¶
例如,考虑此模式:¶
{
"$id": "https://example.net/root.json",
"items": {
"type": "array",
"items": { "$ref": "#item" }
},
"$defs": {
"single": {
"$anchor": "item",
"type": "object",
"additionalProperties": { "$ref": "other.json" }
}
}
}
¶
当实现遇到 <#/$defs/single> 模式时, 它会将 "$anchor" 值作为片段名称,根据当前 基础 URI 解析,形成 <https://example.net/root.json#item>。¶
当实现随后查看 <#/items> 模式内部时,它 遇到 <#item> 引用,并将其解析为 <https://example.net/root.json#item>,这是它已在 同一文档中看到定义的,因此可以自动使用。¶
当实现遇到对 "other.json" 的引用时,它会将其解析为 <https://example.net/other.json>,该 URI 未在此 文档中定义。如果具有该标识符的模式已通过其他方式提供给 实现,它也可以被自动使用。 当被引用模式未知时,实现应做什么? 是否存在允许自动网络解引用的情况? 同源策略?用户可配置选项?在由 Hyper-Schema 描述的 演进式 API 中,预计新模式会被动态添加到系统, 因此要求绝对预加载模式文档不可行。 ¶
由于 JSON Pointer URI 片段是基于模式文档结构 构造的,因此嵌入式模式资源及其子模式 可以通过相对于其自身规范 URI 的 JSON Pointer 片段, 或相对于任何包含资源 URI 的 JSON Pointer 片段进行标识。¶
从概念上讲,一组链接的模式资源应当表现 相同,无论每个资源是通过 模式引用(第 8.2.3 节)连接的单独文档, 还是结构化为一个包含一个或多个嵌入为 子模式的模式资源的单个文档。¶
由于相对于父模式资源 URI 的 JSON Pointer 片段所形成的 URI 在嵌入式模式被移动到单独文档并被引用时 不再有效,应用和模式 SHOULD NOT 使用此类 URI 来标识嵌入式模式资源或 其中的位置。¶
考虑以下包含另一个 嵌入式模式资源的模式文档:¶
{
"$id": "https://example.com/foo",
"items": {
"$id": "https://example.com/bar",
"additionalProperties": { }
}
}
¶
URI "https://example.com/foo#/items" 指向 "items" 模式, 该模式是嵌入式资源。然而,该模式 资源的规范 URI 是 "https://example.com/bar"。¶
对于该嵌入式资源内的 "additionalProperties" 模式, URI "https://example.com/foo#/items/additionalProperties" 指向 正确对象,但该对象相对于其资源 规范 URI 的 URI 是 "https://example.com/bar#/additionalProperties"。¶
现在考虑以下两个通过 "$ref" 的 URI 值 按引用链接的模式资源:¶
{
"$id": "https://example.com/foo",
"items": {
"$ref": "bar"
}
}
{
"$id": "https://example.com/bar",
"additionalProperties": { }
}
¶
在这里可以看到,"https://example.com/bar#/additionalProperties" 使用追加到 "bar" 模式资源规范 URI 的 JSON Pointer 片段, 仍然有效,而 "https://example.com/foo#/items/additionalProperties" 依赖 追加到 "foo" 模式资源规范 URI 的 JSON Pointer 片段, 不再解析到任何内容。¶
还要注意,"https://example.com/foo#/items" 在两种 布局中都有效,但解析到不同值。此 URI 最终 的作用类似于资源的检索 URI。虽然该 URI 有效,但除非特别希望标识第二种(非嵌入式)布局中 包含 "$ref" 的对象,否则使用嵌入或被引用 资源的 "$id" 更稳健。¶
实现 MAY 选择不支持使用非资源规范 URI 作为基础,再加上相对于该基础的 JSON Pointer 片段来寻址模式资源 内容。因此,模式 作者 SHOULD NOT 依赖此类 URI,因为使用它们可能降低互操作性。 这样做是为了避免要求实现为每个资源跟踪整套 可能的基础 URI 和 JSON Pointer 片段, 因为除其中一个外,所有这些在模式资源 被重组时都会很脆弱。有些人 认为这很容易,因此没有必要禁止它, 而另一些人认为它使模式标识复杂化, 应该被禁止。欢迎就此 主题提供反馈。 经过一些讨论,我们认为需要移除对 "canonical" 的使用,转而讨论跨越模式资源边界引用的 JSON Pointer 作为未定义行为,甚至作为被禁止的行为 (https://github.com/json-schema-org/json-schema-spec/issues/937, https://github.com/json-schema-org/json-schema-spec/issues/1183) ¶
复合模式文档被定义为一个 JSON 文档(有时称为“打包的”模式), 其中多个嵌入式 JSON Schema 资源被打包到同一文档中, 以便于传输。¶
每个嵌入式模式资源 MUST 被视为单独的模式资源,遵循标准 模式加载和处理要求,包括确定词汇表支持。¶
用于创建复合模式文档的打包过程被定义为取得 对外部模式资源的引用(如 "$ref"),并将被引用的 模式资源嵌入到引用文档中。打包 SHOULD 以这样的方式完成: 基础文档以及任何被引用/嵌入 文档中的所有 URI(用于引用)都不需要修改。¶
每个嵌入式 JSON Schema 资源 MUST 使用 "$id" 关键字以 URI 标识自身, 并且 SHOULD 在该模式资源的根中使用 "$schema" 关键字标识其正在使用的方言。 RECOMMENDED "$id" 的 URI 标识符值为绝对 URI。¶
当按引用应用器所引用的模式资源被打包时,RECOMMENDED 将该模式资源作为包含模式根处 "$defs" 对象的值放置。 现在嵌入的模式资源的 "$defs" 键 MAY 是被打包模式的 "$id", 或某种应用定义的唯一标识符(如 UUID)。此键并不 旨在被 JSON Schema 引用,但可供应用用来辅助 打包过程。¶
模式资源 MAY 被嵌入到 "$defs" 之外的位置,前提是该位置被定义为 模式值。¶
被打包的模式资源 MUST NOT 通过替换引用它的模式对象, 或通过将该模式资源包装在其他应用器关键字中来打包。¶
为了产生相同输出,包含模式文档中指向 之前外部模式资源的引用 MUST NOT 被改变,并且现在会解析为使用 嵌入式模式资源的 "$id" 的模式。此类相同输出包括验证求值以及 在结果注解或错误中使用的 URI 或路径。¶
虽然打包过程通常是创建复合模式文档的主要方式, 但也可能且预期有些复合模式文档是手工创建的, 可能其中各个模式资源此前并未独立存在。¶
当单个文档中存在多个模式资源时, 未定义应使用哪种方言处理的模式资源 MUST 使用与包围资源相同的方言处理。¶
由于任何可被引用的模式也都可以被嵌入,嵌入式模式资源 MAY 使用其包围资源中的 "$schema" 值指定不同的处理方言。¶
鉴于复合模式文档可能包含标识为使用不同 方言的嵌入式资源,SHOULD NOT 通过将元模式 应用于复合模式文档作为实例来验证这些文档。 RECOMMENDED 提供替代 验证过程以验证模式文档。每个模式资源 SHOULD 分别针对其关联的元模式进行验证。 如果你知道正在验证的是模式,则可以通过使用 "$id" 来识别这些模式是否是复合模式文档;当 "$id" 不在文档根处使用时,它会标识嵌入式资源。 ¶
如果复合模式文档中的所有嵌入式资源都标识为使用相同 方言,或 "$schema" 被省略并因此默认为包围资源的方言, 则 MAY 通过应用适当的元模式来验证。¶
模式 MUST NOT 针对实例运行到无限循环中。例如, 如果两个模式 "#alice" 和 "#bob" 都有一个 "allOf" 属性 引用另一个模式,天真的验证器可能会陷入无限 递归循环,试图验证该实例。模式 SHOULD NOT 使用此类无限递归嵌套;其行为未定义。¶
子模式对象(或布尔值)通过其与已知 应用器关键字一起使用,或与 "$defs"(第 8.2.4 节) 等位置保留关键字一起使用来识别; 这些关键字以一个或多个子模式 作为值。这些关键字可以是 "$defs" 和本文档中的标准应用器, 也可以是来自已知词汇表的扩展关键字,或 实现特定的自定义关键字。¶
未知关键字的多层结构能够引入 嵌套子模式,而这些子模式会受到 "$id" 处理规则约束。因此,在这种未识别 结构中拥有引用目标无法可靠实现,结果行为 未定义。类似地,在已知关键字下的引用目标, 如果其值已知不是模式,也会导致未定义 行为,以避免给实现增加检测此类目标的负担。 这些场景类似于通过 HTTP 获取模式, 但收到的响应 Content-Type 不是 application/schema+json。实现当然可以 尝试将其解释为模式,但源服务器 没有保证它确实是这样的东西。 因此,将其解释为模式具有安全影响, 并可能产生不可预测的结果。 ¶
注意,具有与 "$defs" 相同语法和 语义的单层自定义关键字不允许任何中间 "$id" 关键字, 因此在尝试将任何引用目标用作模式的实现下 会正确工作。不过,此行为是 实现特定的,MUST NOT 依赖它实现互操作性。¶
JSON 已被 HTTP 服务器广泛用于自动化 API 和机器人。 本节描述在与支持媒体类型和 Web linking [RFC8288] 的协议一起使用时,如何以更 RESTful 的 方式增强 JSON 文档处理。¶
RECOMMENDED 由模式描述的实例提供指向 可下载 JSON Schema 的链接,并使用 Linked Data Protocol 1.0 第 8.1 节 [W3C.REC-ldp-20150226] 中定义的链接关系 "describedby"。¶
在 HTTP 中,此类链接可以使用 Link 标头 [RFC8288] 附加到任何响应。此类标头的示例如下:¶
Link: <https://example.com/my-hyper-schema>; rel="describedby"
¶
当用于网络上的超媒体系统时, HTTP [RFC7231] 通常是分发模式的首选协议。 行为不当的客户端如果过于频繁地通过网络拉取模式, 可能会给服务器维护者造成问题;而其实可以将模式缓存很长一段 时间。¶
HTTP 服务器 SHOULD 在 JSON Schema 上设置长期缓存标头。 HTTP 客户端 SHOULD 遵守缓存标头,并在 新鲜期内不重新请求文档。 分布式系统 SHOULD 使用共享缓存和/或缓存代理。¶
客户端 SHOULD 设置或前置一个特定于 JSON Schema 实现或软件产品的 User-Agent 标头。由于符号按重要性递减顺序列出, JSON Schema 库名称/版本应位于更 通用的 HTTP 库名称(如有)之前。例如:¶
User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0
¶
客户端 SHOULD 能够使用 "From" 标头发出请求,以便服务器 操作者可以联系潜在行为不当脚本的所有者。¶
本节定义一个应用器关键字词汇表, RECOMMENDED 将其用作其他词汇表的基础。¶
不使用 "$vocabulary" 的元模式 SHOULD 被视为 要求此词汇表,就像其 URI 以 true 值出现一样。¶
此词汇表的当前 URI(称为 Applicator 词汇表)为: <https://json-schema.org/draft/2020-12/vocab/applicator>。¶
对应元模式的当前 URI 为: https://json-schema.org/draft/2020-12/meta/applicator。¶
模式关键字通常独立运行,不会 影响彼此的结果。¶
为了方便模式作者,此词汇表中的 关键字存在一些例外:¶
这些关键字将子模式应用于实例中与父模式 正在应用位置相同的位置。它们允许以各种方式组合 或修改子模式结果。¶
这些关键字的子模式会完全独立地求值实例, 因而一个此类子模式的结果 MUST NOT 影响兄弟 子模式的结果。因此,子模式可以按 任意顺序应用。¶
这些关键字对应于用于组合或修改 子模式布尔断言结果的逻辑运算符。它们对注解收集没有直接 影响,尽管它们使同一注解 关键字能够以不同值应用于某个实例位置。 注解关键字会定义自己的规则来组合此类值。¶
此关键字的值 MUST 是非空数组。 数组的每一项 MUST 是有效的 JSON Schema。¶
如果实例成功通过此关键字值定义的所有模式的验证, 则实例成功通过此关键字的验证。¶
此关键字的值 MUST 是非空数组。 数组的每一项 MUST 是有效的 JSON Schema。¶
如果实例成功通过此关键字值定义的至少一个模式的验证, 则实例成功通过此关键字的验证。 注意,当正在收集注解时,所有子模式 MUST 被检查,以便从每个成功验证的子模式中 收集注解。¶
此关键字的值 MUST 是非空数组。 数组的每一项 MUST 是有效的 JSON Schema。¶
如果实例成功通过此关键字值定义的恰好一个模式的验证, 则实例成功通过此关键字的验证。¶
其中三个关键字协同工作,以根据另一个子模式的结果 实现子模式的条件 应用。第四个是特定条件情况的快捷方式。¶
"if"、"then" 和 "else" MUST NOT 跨 子模式边界彼此交互。换言之,一个 "allOf" 分支中的 "if" MUST NOT 影响另一个分支中的 "then" 或 "else"。¶
当 "if"、"then" 或 "else" 不存在时,没有默认行为。特别是,它们 MUST NOT 被视为以空模式存在,并且当 "if" 不存在时,"then" 和 "else" MUST 被 完全忽略。¶
此关键字的值 MUST 是有效的 JSON Schema。¶
此关键字子模式的验证结果 对整体验证 结果没有直接影响。相反,它控制 "then" 或 "else" 关键字中的哪一个会被求值。¶
成功通过此关键字子模式验证的实例 MUST 也对 "then" 关键字的子模式值有效, 如果该关键字 存在。¶
未能通过此关键字子模式验证的实例 MUST 也对 "else" 关键字的子模式值有效, 如果该关键字 存在。¶
如果正在收集 注解(第 7.7 节), 则会以通常方式从此 关键字的子模式收集注解,包括当 该关键字存在但 "then" 和 "else" 都不存在时。¶
此关键字的值 MUST 是有效的 JSON Schema。¶
当 "if" 存在,且实例成功 通过其子模式验证时,如果该实例也 成功通过此关键字子模式的验证,则针对该关键字的验证 成功。¶
当 "if" 不存在,或 实例未能通过其子模式验证时,此关键字没有效果。 在这些情况下,实现 MUST NOT 为验证或注解收集目的 根据此关键字求值实例。¶
此关键字的值 MUST 是有效的 JSON Schema。¶
当 "if" 存在,且实例未能 通过其子模式验证时,如果该实例 成功通过此关键字子模式的验证,则针对该关键字的验证 成功。¶
当 "if" 不存在,或 实例成功通过其子模式验证时,此关键字没有效果。 在这些情况下,实现 MUST NOT 为验证或注解收集目的 根据此关键字求值实例。¶
此关键字指定当实例是对象并包含某个属性时 要求值的子模式。¶
此关键字的值 MUST 是对象。 对象中的每个值 MUST 是有效的 JSON Schema。¶
如果对象键是实例中的属性,则整个 实例必须针对该子模式验证。它的使用 依赖于该属性的存在。¶
省略此关键字与空对象具有相同行为。¶
这些关键字各自定义一条规则,用于将其 子模式应用于子实例,具体而言是对象 属性和数组项,并组合其结果。¶
"prefixItems" 的值 MUST 是有效 JSON Schema 的非空数组。¶
如果实例的每个元素在存在同位置模式时 都能针对该模式验证,则验证成功。此关键字 不约束数组长度。如果数组长度 大于此关键字的值,则此关键字只验证匹配长度的 前缀。¶
此关键字产生一个注解值,该值是此关键字应用子模式的最大 索引。如果某个子模式被应用到实例的每个 索引,则该值 MAY 是布尔值 true,例如 "items" 关键字产生的值。 此注解会影响 "items" 和 "unevaluatedItems" 的行为。¶
省略此关键字与 空数组具有相同的断言行为。¶
"items" 的值 MUST 是有效的 JSON Schema。¶
此关键字将其子模式应用于实例元素中 索引大于同一模式对象中 "prefixItems" 数组长度的位置, 该长度由该 "prefixItems" 关键字的注解结果报告。 如果不存在此类注解 结果,"items" 会将其子模式应用于所有实例 数组元素。 注意,没有 "prefixItems" 时 "items" 的行为 与先前草案中 "items" 的模式形式相同。 当存在 "prefixItems" 时,"items" 的行为 与以前的 "additionalItems" 关键字相同。 ¶
如果 "items" 子模式被应用于实例数组中的任何 位置,它会产生一个 布尔值 true 的注解结果,表示所有剩余数组 元素都已根据此关键字的子模式求值。 此注解会影响 Unevaluated 词汇表中 "unevaluatedItems" 的行为。¶
省略此关键字与 空模式具有相同的断言行为。¶
实现 MAY 选择以另一种方式实现或优化此关键字, 只要产生相同效果,例如直接 检查 "prefixItems" 数组是否存在及其大小。 不支持注解收集的实现 MUST 这样做。¶
此关键字的值 MUST 是有效的 JSON Schema。¶
如果数组实例的至少一个元素对给定模式有效, 则该数组实例针对 "contains" 有效; 但当存在 "minContains" 且其值为 0 时, 即使没有任何元素对给定模式有效,数组实例 MUST 被视为 对 "contains" 关键字有效。¶
此关键字产生一个注解值,该值是一个数组,包含 此关键字在应用其子模式时成功验证的索引, 按升序排列。如果子模式在应用于 实例的每个索引时均成功验证,则该值 MAY 是布尔值 "true"。 如果此关键字模式所应用到的实例数组 为空,则该注解 MUST 存在。¶
此注解会影响 Unevaluated 词汇表中 "unevaluatedItems" 的行为,并且 MAY 也用于实现 验证词汇表中的 "minContains" 和 "maxContains" 关键字。¶
即使在找到第一个匹配项之后,也 MUST 将子模式应用于每个数组元素, 以便收集供其他关键字使用的注解。 这是为了确保收集所有可能的注解。¶
"properties" 的值 MUST 是对象。 此对象的每个值 MUST 是有效的 JSON Schema。¶
对于同时出现在实例中并作为此关键字值中名称出现的每个名称, 如果该名称对应的子实例成功通过 对应模式的验证,则验证成功。¶
此关键字的注解结果是由此关键字匹配的实例 属性名集合。 此注解会影响 "additionalProperties"(在 此词汇表中)和 Unevaluated 词汇表中 "unevaluatedProperties" 的行为。¶
省略此关键字与 空对象具有相同的断言行为。¶
"patternProperties" 的值 MUST 是对象。此对象的每个属性名 SHOULD 是有效的正则表达式,符合 ECMA-262 正则表达式方言。此对象的每个属性值 MUST 是有效的 JSON Schema。¶
对于匹配此关键字值中作为属性名出现的任何 正则表达式的每个实例名称, 如果该名称对应的子实例成功通过每个 匹配正则表达式所对应模式的验证,则验证成功。¶
此关键字的注解结果是由此关键字匹配的实例 属性名集合。 此注解会影响 "additionalProperties"(在此 词汇表中)和 "unevaluatedProperties"(在 Unevaluated 词汇表中)的行为。¶
省略此关键字与 空对象具有相同的断言行为。¶
"additionalProperties" 的值 MUST 是有效的 JSON Schema。¶
此关键字的行为取决于同一模式对象内 "properties" 和 "patternProperties" 的存在及 注解结果。 使用 "additionalProperties" 的验证仅应用于 未出现在 "properties" 或 "patternProperties" 注解 结果中的实例名称的子 值。¶
对于所有此类属性,如果子实例 针对 "additionalProperties" 模式验证通过,则验证成功。¶
此关键字的注解结果是由此关键字子模式验证的实例 属性名集合。 此注解会影响 Unevaluated 词汇表中 "unevaluatedProperties" 的行为。¶
省略此关键字与 空模式具有相同的断言行为。¶
实现 MAY 选择以另一种方式实现或优化此关键字, 只要产生相同效果,例如直接 根据实例属性集合检查 "properties" 中的名称和 "patternProperties" 中的模式。 不支持注解收集的实现 MUST 这样做。 在定义此选项时,输出格式似乎存在 歧义的可能性。该歧义不影响验证结果, 但会影响结果输出格式。 此歧义允许出现多个有效输出结果,取决于是否使用注解, 或使用“产生相同效果”的 draft-07 方案。 可以理解,失败模式的注解会被丢弃。 更多细节见我们的 [决策 记录](https://github.com/json-schema-org/json-schema-spec/tree/HEAD/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md) 。 ¶
"propertyNames" 的值 MUST 是有效的 JSON Schema。¶
如果实例是对象,则当实例中的每个属性名 都能针对所提供模式验证通过时,此关键字验证通过。 注意,模式正在测试的属性名始终是字符串。¶
省略此关键字与空模式具有相同行为。¶
这些关键字的目的是使模式作者能够将 子模式应用于尚未成功针对任何 相邻关键字的任何动态作用域子模式进行求值的 数组项或对象属性。¶
这些实例项或属性可能已经针对一个或多个 相邻关键字子模式求值失败,例如当 "anyOf" 某个分支中的断言失败时。此类失败求值不被视为 对该项或属性是否已求值有所贡献。 只考虑成功求值。¶
如果数组中的某项或对象属性被“成功求值”,则从逻辑上讲, 它会被视为在预期的对象或数组表示方面有效。 例如,如果某个子模式表示一辆汽车, 要求车轮数在 2 到 4 个之间,而 "wheels" 的值为 6,则该实例 对象不会被“求值”为一辆汽车,"wheels" 属性会被视为 “未求值(未作为已知事物成功求值)”,并且不会保留任何注解。¶
回想一下,相邻关键字是同一模式对象内的关键字, 而动态作用域子模式既包括引用目标,也包括 词法子模式。¶
这些关键字的行为取决于适用于正在验证的实例位置的 相邻关键字注解结果。¶
不使用 "$vocabulary" 的元模式 SHOULD 被视为 要求此词汇表,就像其 URI 以 true 值出现一样。¶
此词汇表的当前 URI(称为 Unevaluated Applicator 词汇表)为: <https://json-schema.org/draft/2020-12/vocab/unevaluated>。¶
对应元模式的当前 URI 为: https://json-schema.org/draft/2020-12/meta/unevaluated。¶
模式关键字通常独立运行,不会 影响彼此的结果。不过,此 词汇表中的关键字是值得注意的例外:¶
"unevaluatedItems" 的值 MUST 是有效的 JSON Schema。¶
此关键字的行为取决于适用于正在验证的实例位置的 相邻关键字注解结果。 具体而言,来自 "prefixItems"、"items" 和 "contains" 的注解, 当这些关键字与 "unevaluatedItems" 关键字相邻时,可以由它们产生。这三个注解以及 "unevaluatedItems",也可以由任意和所有相邻的 就地应用器(第 10.2 节)关键字产生。 这包括但不限于本文档中定义的就地应用器。¶
如果不存在相关注解,则 "unevaluatedItems" 子模式 MUST 应用于数组中的所有位置。 如果任何相关注解中存在布尔 true 值, 则 "unevaluatedItems" MUST 被忽略。否则,该子模式 MUST 应用于任何大于 "prefixItems" 最大注解 值的索引,且该索引不出现在任何 "contains" 注解值中。¶
这意味着 "prefixItems"、"items"、"contains" 以及所有就地 应用器 MUST 先于此关键字完成求值,之后此关键字才能被求值。 扩展关键字作者 MUST NOT 定义需要在此关键字之后 求值的就地应用器。¶
如果 "unevaluatedItems" 子模式被应用于实例数组中的任何 位置,它会产生一个 布尔 true 的注解结果,类似于 "items" 的行为。 此注解会影响父模式中 "unevaluatedItems" 的行为。¶
省略此关键字与 空模式具有相同的断言行为。¶
"unevaluatedProperties" 的值 MUST 是有效的 JSON Schema。¶
此关键字的行为取决于适用于正在验证的实例位置的 相邻关键字注解结果。 具体而言,来自 "properties"、"patternProperties" 和 "additionalProperties" 的注解,当这些关键字与 "unevaluatedProperties" 关键字相邻时,可以由它们产生。这 三个注解以及 "unevaluatedProperties",也可以 由任意和所有相邻的 就地应用器(第 10.2 节)关键字产生。 这包括但不限于本文档中定义的就地应用器。¶
使用 "unevaluatedProperties" 的验证仅应用于 未出现在适用于正在验证的 实例位置的 "properties"、 "patternProperties"、"additionalProperties" 或 "unevaluatedProperties" 注解结果中的实例名称的子 值。¶
对于所有此类属性,如果子实例 针对 "unevaluatedProperties" 模式验证通过,则验证成功。¶
这意味着 "properties"、"patternProperties"、"additionalProperties" 以及所有就地应用器 MUST 先于此关键字完成求值, 之后此关键字才能被求值。扩展关键字作者 MUST NOT 定义 需要在此关键字之后求值的就地 应用器。¶
此关键字的注解结果是由此关键字子模式验证的实例 属性名集合。 此注解会影响父模式中 "unevaluatedProperties" 的行为。¶
省略此关键字与 空模式具有相同的断言行为。¶
JSON Schema 被定义为平台无关。因此,为了提高跨平台 兼容性,实现 SHOULD 符合标准验证输出 格式。本节描述消费者正确 解释验证结果所需的最低要求。¶
JSON Schema 输出使用第 4.2.1 节所述的 JSON Schema 数据实例模型定义。 实现 MAY 根据其特定语言和平台所支持的方式偏离此模型, 但 RECOMMENDED 输出应能通过序列化或其他方式 转换为此处定义的 JSON 格式。¶
本规范定义四种输出格式。各格式的要求见“输出结构” 一节。¶
实现 SHOULD 至少提供 "flag"、"basic" 或 "detailed" 格式之一,并 MAY 提供 "verbose" 格式。如果它提供一个或多个 "detailed" 或 "verbose" 格式,则 MUST 同时提供 "flag" 格式。 实现 SHOULD 在其文档中说明支持哪些格式。¶
除简单的 "flag" 输出之外,额外信息有助于 调试模式或实例。每个子结果 SHOULD 至少包含本节中 包含的信息。¶
包含所有这些组件的单个对象被视为 一个输出单元。¶
实现 MAY 选择提供额外信息。¶
跟随验证路径的验证关键字的相对位置。 该值 MUST 表示为 JSON Pointer,并且 MUST 包含 任何按引用应用器,例如 "$ref" 或 "$dynamicRef"。¶
/properties/width/$ref/minimum¶
注意,由于包含这些按引用应用器关键字, 此指针可能无法通过普通 JSON Pointer 过程解析。¶
此信息的 JSON 键是 "keywordLocation"。¶
验证关键字的绝对、已解引用位置。该值 MUST 表示为完整 URI,使用相关模式资源的规范 URI 并带有 JSON Pointer 片段,并且 MUST NOT 将 "$ref" 或 "$dynamicRef" 等按引用应用器作为非终止路径组件包含。 如果错误或注解针对的是此类 关键字,例如不可解析的引用,则它 MAY 以此类关键字结尾。 注意,此处的 "absolute" 是指“绝对文件系统路径” 意义上的绝对(即完整位置),而不是 RFC 3986 中 "absolute-URI" 术语意义上的绝对(即带 scheme 但不带片段)。 关键字绝对位置会带有片段,以便 标识该关键字。 ¶
https://example.com/schemas/common#/$defs/count/minimum¶
仅当动态作用域未经过引用,或模式未将绝对 URI 声明为其 "$id" 时, 此信息 MAY 被省略。¶
此信息的 JSON 键是 "absoluteKeywordLocation"。¶
正在验证的实例中 JSON 值的位置。该 值 MUST 表示为 JSON Pointer。¶
此信息的 JSON 键是 "instanceLocation"。¶
验证产生的错误或注解。¶
对于错误,本规范不定义消息的具体措辞。 实现需要提供此内容。¶
对于注解,产生注解的每个关键字会指定其 格式。默认情况下,它是该关键字的值。¶
验证失败时,此信息的 JSON 键是 "error";验证成功时 是 "annotation"。¶
对于两种层级结构,此属性将保存嵌套错误 和注解。¶
在验证失败时,嵌套结果的 JSON 键是 "errors";在 验证成功时是 "annotations"。注意复数形式,因为 具有嵌套结果的关键字也可以有本地错误或注解。¶
输出 MUST 是包含名为 "valid" 的布尔属性的对象。当 需要有关结果的额外信息时,输出 MUST 还包含 下文所述的 "errors" 或 "annotations"。¶
对于这些示例,将使用以下模式和实例。¶
{
"$id": "https://example.com/polygon",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"point": {
"type": "object",
"properties": {
"x": { "type": "number" },
"y": { "type": "number" }
},
"additionalProperties": false,
"required": [ "x", "y" ]
}
},
"type": "array",
"items": { "$ref": "#/$defs/point" },
"minItems": 3
}
[
{
"x": 2.5,
"y": 1.3
},
{
"x": 1,
"z": 6.7
}
]
¶
此实例将验证失败并产生错误,但可以很容易推导出 通过模式并产生注解的示例。¶
具体而言,它将产生的错误是:¶
注意,这些示例中显示的错误消息措辞并不是本 规范的要求。实现 SHOULD 为其受众定制错误消息, 或提供模板机制,允许用户 编写自己的消息。¶
在最简单的情况下,只需要满足 "valid" 属性的布尔结果。¶
{
"valid": false
}
¶
由于此格式不会返回错误或注解,因此 RECOMMENDED 实现使用短路逻辑,一旦能够确定结果, 就返回失败或成功。例如, 如果 "anyOf" 关键字包含五个子模式,而第二个 通过,则不需要检查其他三个。逻辑可以直接 返回成功。¶
"Basic" 结构是输出单元的扁平列表。¶
{
"valid": false,
"errors": [
{
"keywordLocation": "",
"instanceLocation": "",
"error": "A subschema had errors."
},
{
"keywordLocation": "/items/$ref",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point",
"instanceLocation": "/1",
"error": "A subschema had errors."
},
{
"keywordLocation": "/items/$ref/required",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/required",
"instanceLocation": "/1",
"error": "Required property 'y' not found."
},
{
"keywordLocation": "/items/$ref/additionalProperties",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/additionalProperties",
"instanceLocation": "/1/z",
"error": "Additional property 'z' found but was invalid."
},
{
"keywordLocation": "/minItems",
"instanceLocation": "",
"error": "Expected at least 3 items but found 2"
}
]
}
¶
"Detailed" 结构基于模式,对于人类和机器都更具可读性。 以这种方式组织结构,会使错误之间的关联 更明显。例如,缺失 "y" 属性和额外 "z" 属性 都源于实例中的同一位置这一事实, 在 "Basic" 结构中并不立即显而易见。 在层级结构中,这种相关性更容易识别。¶
以下规则约束结果对象的构造:¶
分支节点不需要错误消息或注解。¶
{
"valid": false,
"keywordLocation": "",
"instanceLocation": "",
"errors": [
{
"valid": false,
"keywordLocation": "/items/$ref",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point",
"instanceLocation": "/1",
"errors": [
{
"valid": false,
"keywordLocation": "/items/$ref/required",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/required",
"instanceLocation": "/1",
"error": "Required property 'y' not found."
},
{
"valid": false,
"keywordLocation": "/items/$ref/additionalProperties",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/additionalProperties",
"instanceLocation": "/1/z",
"error": "Additional property 'z' found but was invalid."
}
]
},
{
"valid": false,
"keywordLocation": "/minItems",
"instanceLocation": "",
"error": "Expected at least 3 items but found 2"
}
]
}
¶
"Verbose" 结构是一个完全展开的层级结构,精确匹配 模式的结构。此结构适用于表单生成和 验证,其中错误的位置很重要。¶
它与 "Detailed" 结构之间的主要区别是 返回所有结果。这包括原本会被移除的子模式验证结果 (例如失败验证的注解、`not` 关键字内部的 成功验证等)。因此, RECOMMENDED 每个节点还携带 `valid` 属性,以指示该节点的 验证结果。¶
由于此输出结构可能相当大,为简洁起见,此处给出 一个较小示例。上面示例完整输出结构的 URI 为: https://json-schema.org/draft/2020-12/output/verbose-example。¶
// schema
{
"$id": "https://example.com/polygon",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"validProp": true,
},
"additionalProperties": false
}
// instance
{
"validProp": 5,
"disallowedProp": "value"
}
// result
{
"valid": false,
"keywordLocation": "",
"instanceLocation": "",
"errors": [
{
"valid": true,
"keywordLocation": "/type",
"instanceLocation": ""
},
{
"valid": true,
"keywordLocation": "/properties",
"instanceLocation": ""
},
{
"valid": false,
"keywordLocation": "/additionalProperties",
"instanceLocation": "",
"errors": [
{
"valid": false,
"keywordLocation": "/additionalProperties",
"instanceLocation": "/disallowedProp",
"error": "Additional property 'disallowedProp' found but was invalid."
}
]
}
]
}
¶
为方便起见,已提供 JSON Schema 用于验证 实现生成的输出。其 URI 为: https://json-schema.org/draft/2020-12/output/schema。¶
模式和实例都是 JSON 值。因此, RFC 8259 [RFC8259] 中定义的所有安全考量均适用。¶
实例和模式都经常由不受信任的第三方编写,并 部署在公共 Internet 服务器上。 验证器应注意,根据模式进行解析和验证不应消耗过多的 系统资源。 验证器 MUST NOT 陷入无限循环。¶
恶意方可能导致实现反复收集某个非常大值的副本 作为注解。实现 SHOULD 防范 此类场景中过度消耗系统资源。¶
服务器 MUST 确保恶意方无法通过上传带有 既有或非常相似 "$id" 的模式来改变 现有模式的功能。¶
各个 JSON Schema 词汇表也可能具有自己的安全 考量。更多信息请参阅相应规范。¶
模式作者应谨慎处理 "$comment" 内容,因为恶意 实现可能违反规范将其显示给最终用户,或 在预期移除它们时未能移除。¶
恶意模式作者可能在 "$comment" 中放置可执行代码或其他危险 材料。实现 MUST NOT 基于 "$comment" 内容进行解析或以其他方式 采取操作。¶
为 JSON Schema 提议的 MIME 媒体类型定义如下:¶
为需要 JSON Schema 特定媒体类型的 JSON Schema 实例 提议的 MIME 媒体类型定义如下:¶
考虑以下模式,它展示了如何使用 "$id" 来标识 根模式和各种子模式,以及如何使用 "$anchor" 定义普通名称片段标识符。¶
{
"$id": "https://example.com/root.json",
"$defs": {
"A": { "$anchor": "foo" },
"B": {
"$id": "other.json",
"$defs": {
"X": { "$anchor": "bar" },
"Y": {
"$id": "t/inner.json",
"$anchor": "bar"
}
}
},
"C": {
"$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"
}
}
}
¶
以下 URI 编码的 JSON Pointer [RFC6901](相对于根模式)处的模式 具有以下 基础 URI,并且可根据上文第 5 节和 9.2.1 节由任何列出的 URI 标识。¶
注意:URI 的片段部分并不会使其成为规范或非规范; 相反,用作基础的 URI(作为带有任何片段的完整 URI 的一部分) 才决定所得完整 URI 的规范性质。 多个“规范”URI?我们承认这可能造成困惑,并 建议你阅读 JSON Pointer 片段与嵌入式模式资源(第 9.2.1 节) 一节中的 CREF,以了解进一步评论。 ¶
已经创建了各种工具,用于根据引用("$ref") 出现的方式和位置重新排列模式文档。本附录讨论 哪些用例和操作符合本规范。¶
一组旨在共同使用的模式资源,可以组织为 每个资源位于自己的模式文档中,也可以全部位于同一个模式文档中, 或者采用介于两者之间的任何文档分组粒度。¶
存在许多工具可执行各种形式的引用移除。 一个常见情况是生成单个文件,使所有引用 都能在该文件内解析。这通常用于简化 分发,或简化编码,使 JSON Schema 库的各种调用 不必跟踪和加载 大量资源。¶
只要所有静态引用(例如 "$ref")都使用 URI-reference, 并且这些引用解析到的 URI 使用规范资源 URI 作为基础, 且所有模式资源都在其根模式的 "$id" 中具有 absolute-URI,就可以安全且可逆地执行此转换。¶
在满足这些条件时,每个外部资源都可以复制到 "$defs" 下,而不会破坏资源的模式对象之间的任何引用, 也不会改变验证或注解结果的任何方面。 "$defs" 下模式的名称不会影响行为,假设它们 各自唯一,因为它们不会出现在嵌入式资源的 规范 URI 中。¶
尝试移除所有引用并生成单个模式文档,并不 在所有情况下都产生与原始形式行为相同的模式。¶
由于 "$ref" 现在像其他任何关键字一样处理, 并允许其他关键字出现在同一模式对象中, 在所有情况下完全支持非递归 "$ref" 移除可能 需要相对复杂的模式操作。确定或提供一组安全的 "$ref" 移除转换超出了本规范范围,因为它们不仅取决于模式结构, 还取决于预期用途。¶
考虑以下两个模式,它们描述了一个简单的 递归树结构,其中树中的每个节点 都可以有一个任意类型的 "data" 字段。第一个模式 允许并忽略其他实例属性。第二个模式 更严格,只允许 "data" 和 "children" 属性。 还展示了一个将 "data" 拼错为 "daat" 的示例实例。¶
// tree schema, extensible
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/tree",
"$dynamicAnchor": "node",
"type": "object",
"properties": {
"data": true,
"children": {
"type": "array",
"items": {
"$dynamicRef": "#node"
}
}
}
}
// strict-tree schema, guards against misspelled properties
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/strict-tree",
"$dynamicAnchor": "node",
"$ref": "tree",
"unevaluatedProperties": false
}
// instance with misspelled field
{
"children": [ { "daat": 1 } ]
}
¶
当我们加载这两个模式时,会注意到每个模式中都存在 名为 "node" 的 "$dynamicAnchor"(注意没有 "#", 因为这只是名称),从而产生以下完整模式 URI:¶
此外,JSON Schema 实现会跟踪这些片段是 使用 "$dynamicAnchor" 创建的这一事实。¶
如果我们将 "strict-tree" 模式应用于实例,就会跟随 "$ref" 到 "tree" 模式,检查其 "children" 子模式, 并在其 "items" 子模式中找到指向 "#node" 的 "$dynamicRef": (注意 "#" 用于 URI 片段语法)。 该引用解析为 "https://example.com/tree#node",这是一个带有 由 "$dynamicAnchor" 创建的片段的 URI。因此,在跟随引用之前, 我们必须检查动态作用域。¶
此时,动态路径为 "#/$ref/properties/children/items/$dynamicRef",其动态作用域 包含(从最外层作用域到最内层):¶
由于我们正在查找普通名称片段,而这种片段可以在 模式资源中的任何位置定义,因此 JSON Pointer 片段 与此检查无关。这意味着我们可以移除这些 片段并消除连续重复项,得到:¶
在这种情况下,最外层资源也具有一个由 "$dynamicAnchor" 定义的 "node" 片段。因此,我们不是将 "$dynamicRef" 解析为 "https://example.com/tree#node",而是将其解析为 "https://example.com/strict-tree#node"。¶
这样,"tree" 模式中的递归会递归到 "strict-tree" 的根,而不是只将 "strict-tree" 应用于 实例根、却将 "tree" 应用于实例子节点。¶
此示例展示了两个 "$dynamicAnchor" 在每个模式中的同一位置, 具体来说是在资源根模式中。 由于普通名称片段独立于 JSON 结构, 即使一个或两个 node 模式对象 被移动到 "$defs" 下,这也同样有效。告诉我们如何解析动态引用的 是匹配的 "$dynamicAnchor" 值, 而不是 JSON 结构中的任何形式的对应关系。¶
词汇表作者应 注意避免关键字名称冲突,特别是当该词汇表旨在 广泛使用,并可能与其他词汇表组合时。JSON Schema 不提供任何正式的命名空间系统,但也 不约束关键字名称,因此允许任意数量的命名空间 方法。¶
词汇表可以相互构建,例如根据另一个 词汇表中关键字的行为来定义其关键字的行为, 或者使用另一个词汇表中的关键字,但对 可接受值集合进行限制或扩展。并非所有此类 词汇表复用都会产生与其所构建于的词汇表 兼容的新词汇表。词汇表作者应 清楚记录预期的兼容级别(如果有)。¶
元模式作者不应使用 "$vocabulary" 来组合多个 对同一关键字定义冲突语法或语义的词汇表。 由于语义冲突通常无法通过 模式验证检测到,因此不期望实现检测此类 冲突。如果声明了冲突词汇表,所得 行为未定义。¶
词汇表作者 SHOULD 提供一个元模式,用于验证 该词汇表关键字本身的预期用法。此类元模式 SHOULD 不禁止额外关键字,并且 MUST 不禁止 Core 词汇表中的任何关键字。¶
建议元模式作者使用 "allOf"(第 10.2.1.1 节) 关键字引用每个词汇表的 元模式, 虽然其他构造元模式的机制也可能适用于 某些用例。¶
元模式的递归性质使 "$dynamicAnchor" 和 "$dynamicRef" 关键字在扩展 现有元模式时特别有用,这一点可从扩展 Validation 元模式的 JSON Hyper-Schema 元模式中看到。¶
元模式可以施加额外约束,包括描述 不存在于任何词汇表中的关键字,超出与声明词汇表 关联的元模式所描述的内容。这允许 将用法限制为某个词汇表的子集,并验证 不打算复用的本地定义关键字。¶
不过,元模式不应与其声明的任何词汇表 相矛盾,例如要求与词汇表所期望不同的 JSON 类型。 所得行为未定义。¶
用于本地用途、且无需在任意实现中测试 词汇表支持的元模式,可以安全地完全省略 "$vocabulary"。¶
此元模式显式声明 Core 和 Applicator 词汇表, 以及一个扩展词汇表,并使用 "allOf" 组合它们的元模式。扩展词汇表的元模式 只描述该词汇表中的关键字,在主示例元模式之后展示。¶
主示例元模式还通过禁止以 "unevaluated" 为前缀的关键字, 限制 Unevaluated 词汇表的使用,因为这些关键字实现起来特别复杂。 这不会改变其他词汇表所定义的语义或关键字集合。 它只是确保使用此元模式的模式在尝试使用 以 "unevaluated" 为前缀的关键字时,无法通过此元模式验证。¶
最后,此元模式描述了一个不属于任何词汇表的关键字 "localKeyword" 的语法。大概此元模式的实现者和用户 会理解 "localKeyword" 的语义。 JSON Schema 没有定义任何机制来表达词汇表之外的 关键字语义,因此除非在理解它们的 特定环境中,否则它们不适合使用。¶
此元模式组合了几个用于一般用途的词汇表。¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/meta/general-use-example",
"$dynamicAnchor": "meta",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://example.com/vocab/example-vocab": true
},
"allOf": [
{"$ref": "https://json-schema.org/draft/2020-12/meta/core"},
{"$ref": "https://json-schema.org/draft/2020-12/meta/applicator"},
{"$ref": "https://json-schema.org/draft/2020-12/meta/validation"},
{"$ref": "https://example.com/meta/example-vocab"}
],
"patternProperties": {
"^unevaluated": false
},
"properties": {
"localKeyword": {
"$comment": "Not in vocabulary, but validated if used",
"type": "string"
}
}
}
¶
此元模式只描述单个扩展词汇表。¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/meta/example-vocab",
"$dynamicAnchor": "meta",
"$vocabulary": {
"https://example.com/vocab/example-vocab": true,
},
"type": ["object", "boolean"],
"properties": {
"minDate": {
"type": "string",
"pattern": "\d\d\d\d-\d\d-\d\d",
"format": "date",
}
}
}
¶
如上所示,尽管 general-use 元模式的 "allOf" 中引用的每个单词汇表元模式都声明了其 对应词汇表,但这个新元模式必须重新声明它们。¶
由 Core 和 Validation 规范定义的、组合所有词汇表的 标准元模式,以及由这些规范和 Hyper-Schema 规范 定义的、组合所有词汇表的标准元模式, 展示了更多复杂组合。这些 元模式的 URI 可分别在 Validation 和 Hyper-Schema 规范中找到。¶
虽然 general-use 元模式可以验证 "minDate" 的语法, 但定义 "minDate" 语义含义背后逻辑的是该词汇表。 如果不了解其语义(在此示例中, 实例值必须是一个等于或晚于模式中作为该关键字值提供日期的日期), 实现只能验证语法用法。在这种情况下,这意味着验证 它是一个日期格式字符串(使用 "pattern" 来确保即使 "format" 纯粹作为注解发挥作用时也会进行验证,正如 Validation 规范 [json-schema-validation]中所解释的)。¶
虽然预期引用的存在对验证结果是透明的, 但代码生成器和 UI 渲染器等生成式用例 通常会认为引用在语义上具有重要意义。¶
为了明确此类用例特定的语义,最佳实践 是创建一个注解关键字,用于与 "$ref" 等 引用关键字并列出现在同一 模式对象中。¶
例如,下面是一个假设性关键字,用于确定 代码生成器是否应将引用 目标视为不同的类,以及这些类之间如何相关。 注意,此示例仅用于说明目的,并不 旨在提出一个可用的代码生成关键字。¶
{
"allOf": [
{
"classRelation": "is-a",
"$ref": "classes/base.json"
},
{
"$ref": "fields/common.json"
}
],
"properties": {
"foo": {
"classRelation": "has-a",
"$ref": "classes/foo.json"
},
"date": {
"$ref": "types/dateStruct.json",
}
}
}
¶
在这里,此模式表示某种面向对象类。 "allOf" 中的第一个引用被标注为基类。 第二个引用未分配类关系,这意味着 代码生成器应将目标的定义与此定义组合, 就好像没有涉及引用一样。¶
查看这些属性,"foo" 被标记为对象组合, 而 "date" 属性没有。它只是一个带有 子字段的字段,而不是某个不同类的实例。¶
这种使用风格要求注解与引用位于同一对象中, 并且该引用必须可被识别为引用。¶
感谢 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 对本文档提交内容和补丁。¶
本节将在离开 Internet-Draft 状态前移除。¶