互联网工程任务组 | A. Wright,编辑 |
互联网草案 | |
预期状态:信息性 | H. Andrews,编辑 |
过期日期:2017 年 10 月 23 日 | Cloudflare, Inc. |
G. Luff | |
2017 年 4 月 21 日 |
JSON 超级模式:用于 JSON 超媒体注释的词汇表
draft-wright-json-schema-hyperschema-01
JSON 模式是一种基于 JSON 的格式,用于定义 JSON 数据的结构。本文档指定了 JSON 模式的超链接和超媒体相关关键字,用于使用超链接和通过像 HTTP 这样的超媒体环境处理和操作远程 JSON 资源的说明对 JSON 文档进行注释。
此草案的议题列表可以在 <https://github.com/json-schema-org/json-schema-spec/issues> 中找到。
有关更多信息,请参见 <https://json-schema.fullstack.org.cn/>。
要提供反馈,请使用此问题跟踪器、主页上列出的通信方式或向文档编辑发送电子邮件。
此互联网草案完全符合 BCP 78 和 BCP 79 的规定。
互联网草案是互联网工程任务组 (IETF) 的工作文档。请注意,其他组也可能以互联网草案的形式分发工作文档。当前互联网草案的列表位于 http://datatracker.ietf.org/drafts/current/。
互联网草案是草案文件,有效期最长为六个月,并且可能在任何时候被其他文件更新、替换或作废。将互联网草案用作参考材料或引用它们,除了作为“正在进行中的工作”之外,都是不合适的。
此互联网草案将于 2017 年 10 月 23 日过期。
版权所有 (c) 2017 IETF 信托和识别为文档作者的人员。保留所有权利。
本文件受 BCP 78 和 IETF 信托的《与 IETF 文档相关的法律条款》(http://trustee.ietf.org/license-info) 的约束,这些条款在本文件发布之日生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文件摘录的代码组件必须包含简化的 BSD 许可证文本,如信托法律条款第 4.e 节所述,并且按简化的 BSD 许可证所述提供,不提供任何保证。
JSON 模式是一种基于 JSON 的格式,用于定义 JSON 数据的结构。本文档指定了 JSON 模式的超链接和超媒体相关关键字。
术语 JSON 超级模式用于指代使用这些关键字的 JSON 模式。
本规范将使用 JSON 模式核心规范 [json-schema] 中定义的术语。建议读者手头有一份该规范的副本。
本文件中出现的关键词“必须”、“禁止”、“必需”、“应”、“不应”、“建议”、“不建议”、“推荐”、“可以”和“可选”应按 RFC 2119 [RFC2119] 中描述的含义进行解释。
术语“模式”和“实例”应按 JSON 模式核心规范 [json-schema] 中的定义进行解释。
本文档描述了如何使用 JSON 模式在实例数据上定义超链接。它还定义了如何提供解释 JSON 数据作为丰富的多媒体文档所需的其他信息。
与所有 JSON 模式关键字一样,“模式关键字”部分中描述的所有关键字都是可选的。最小的有效 JSON 超级模式是空对象。
以下是一个示例 JSON 模式,它定义了超链接,并为“imgData”属性提供了多媒体解释
{ "title": "Written Article", "type": "object", "properties": { "id": { "title": "Article Identifier", "type": "number", "readOnly": true }, "title": { "title": "Article Title", "type": "string" }, "authorId": { "type": "integer" }, "imgData": { "title": "Article Illustration (thumbnail)", "type": "string", "media": { "binaryEncoding": "base64", "type": "image/png" } } }, "required" : ["id", "title", "authorId"], "links": [ { "rel": "self", "href": "/article{?id}" }, { "rel": "author", "href": "/user?id={authorId}" } ] }
此示例模式定义了实例的属性。对于“imgData”属性,它指定应将其作为 base64 解码,并将生成的二进制数据视为 PNG 图像。它还定义了实例的链接关系,其 URI 包含来自实例的值。 [CREF1]"id" 通常不应该是一个必需的关键字,因为新实例将具有未知的 "id" 属性,直到它被服务器分配。但是,此属性用于链接,没有它,多个不同的实例将被赋予相同的 rel=self URI!
以下是上述模式描述的 JSON 实例的示例
{ "id": 15, "title": "Example data", "authorId": 105, "imgData": "iVBORw...kJggg==" }
为了便于阅读,已对 base-64 数据进行了缩写。
如果实例无法通过超模式本身或包含超模式的验证关键字的验证,则禁止将超模式应用于实例。位于“anyOf”或“oneOf”中无法验证的分支,或位于与实例无关的“dependencies”子模式中的超模式关键字,必须被忽略。
位于“not”中的子模式中的超模式关键字(无论深度如何,包括任意数量的中间“not”子模式)必须被忽略。
如果“contains”关键字的子模式包含超模式关键字,则它们必须应用于所有通过该模式验证的数组元素。虽然找到一个验证元素足以确定验证结果,但是当存在超模式关键字时,必须针对所有数组元素对子模式进行评估。
JSON 模式验证的当前 URI 是 <https://json-schema.fullstack.org.cn/draft-06/hyper-schema#>。
如果存在,则此关键字将针对包含整个实例的当前 URI 基地址解析,并为实例内的 URI 引用设置新的 URI 基地址。因此,它是第一个解析的 URI 引用,无论它在哪个顺序找到。
URI 是使用与 "href" [href] 属性中描述的相同过程,从提供的 URI 模板计算出来的。
使用“base”的 JSON 模式示例
{ "base": "/object/{id}", "links": [ { "rel": "self", "href": "" }, { "rel": "next", "href": "{nextId}" } ] }
使用此模式生成 rel="self" 和 rel="next" 链接的 JSON 实例示例
{ "id": 41, "nextId": 42 }
如果文档 URI 是 <http://example.com/?id=41>,则新的 URI 基地址将变为 <http://example.com/object/41>
针对此 URI 基地址解析两个链接描述对象,将创建两个链接,与以下绝对形式 HTTP 链接头完全相同
模式的“links”属性用于将链接描述对象与实例关联。此属性的值必须是一个数组,并且数组中的项目必须是链接描述对象,如下所述。
使用“links”关键字的示例模式可能如下所示
{ "title": "Schema defining links", "links": [ { "rel": "self", "href": "{id}" }, { "rel": "parent", "href": "{parent}" } ] }
“media”属性表明此实例包含以 JSON 字符串编码的非 JSON 数据。它描述了内容的类型以及如何编码。
此属性的值必须是一个对象。如果描述的实例不是字符串,则应忽略此属性的值。
“media”关键字的值可以包含以下任何属性
如果实例值是字符串,则此属性定义应将该字符串解释为二进制数据,并使用此属性命名的编码对其进行解码。 RFC 2045,第 6.1 节 [RFC2045] 列出了此属性的可能值。
此属性的值必须是媒体类型,如 RFC 2046 [RFC2046] 所定义。此属性定义了此模式定义的实例的媒体类型。
如果未设置“binaryEncoding”属性,但实例值是字符串,则此属性的值应指定文本文档类型,并且字符集应是 JSON 字符串值解码到的字符集(默认值为 Unicode)。
以下是一个示例模式,说明了“media”的使用
{ "type": "string", "media": { "binaryEncoding": "base64", "type": "image/png" } }
此模式描述的实例应为字符串,其值应可解释为 base64 编码的 PNG 图像。
另一个示例
{ "type": "string", "media": { "type": "text/html" } }
此模式描述的实例应为包含 HTML 的字符串,使用 JSON 字符串解码到的任何字符集(默认值为 Unicode)。
如果它的值为布尔值 true,则此关键字表示实例的值完全由服务器或拥有方管理,并且预期用户代理修改此属性的值的尝试将被服务器忽略或拒绝。
例如,此属性将用于将服务器生成的序列号标记为只读。
此关键字的值必须是布尔值。默认值为 false。
链接描述对象 (LDO) 用于描述从实例到另一个资源的单个链接关系。链接描述对象必须是一个对象。
链接描述格式可以在没有 JSON 模式的情况下使用,并且可以通过将规范性链接描述模式作为使用链接的数据结构的模式进行引用来声明此格式的使用。规范性链接描述模式的 URI 是:https://json-schema.fullstack.org.cn/draft-06/links(draft-06 版本)。
[CREF2]注意,虽然当前草案没有提供明确指示 HTTP 方法支持的方法,但可能会在将来的草案中添加以某种方式提供非权威性提示(请参见 GitHub 存储库中的问题 #73)。
客户端可以使用数据与链接交互的方式有几种
这三种使用客户端提供数据的方法分别由链接描述对象中的单独模式关键字解决。链接操作忽略与其语义无关的模式。
链接描述对象不会直接指示目标资源支持的操作,例如 HTTP 方法。相反,操作应主要从链接关系类型 [rel]和 URI 模式推断。但是请注意,资源可能始终在运行时拒绝操作,例如由于控制操作可用性的应用程序状态。
默认情况下,"href" [href] 中的 URI 模板变量从服务器提供的实例数据解析。 "hrefSchema" [hrefSchema] 允许链接指定一个模式,用于从客户端提供的数据中解析模板变量。可以使用常规的 JSON 模式验证功能来要求从用户代理数据解析,禁止解析或允许用户代理数据,同时在没有提供用户代理数据的情况下回退到服务器提供的实例数据。
使用服务器提供的实例数据解析模板化的路径组件,同时接受用户代理数据来构建查询字符串的常见模式可以通过将路径模板变量的“hrefSchema”子模式设置为 false 来实现,同时给出查询字符串模板变量名称,这些名称不会出现在实例中。这确保路径变量只能从实例解析,查询字符串变量只能从用户代理数据解析。有关此方法的示例,请参阅“hrefSchema”部分。
在 JSON 超级模式中,"targetSchema" [targetSchema] 提供了对目标资源表示的非权威描述。客户端可以使用“targetSchema”来构建用于替换或修改表示的输入。或者,如果“targetSchema”不存在或客户端更愿意只使用权威信息,则可以与目标资源交互以确认或发现其表示结构。
"targetSchema" 不打算描述链接操作响应,除非响应语义表明它是目标资源的表示。在所有情况下,响应本身指示的模式都是权威的。有关使用“targetSchema”与 HTTP URI 时的特定于每种 HTTP 方法的指南,请参阅第 6.6.1 节。
"submissionSchema" [submissionSchema] 和 "submissionEncType" [submissionEncType] 关键字描述了目标资源实现的处理函数的域。否则,如上所述,提交模式和编码将被忽略,因为它们与不相关的操作无关。
“href”链接描述属性的值是一个模板,用于确定相关资源的目标 URI。实例属性的值必须解析为相对于实例的基本 URI 的 URI 引用 [RFC3986]。
此属性是必需的。
[CREF3]由于早期草案中存在的预处理规则过于复杂,并且无法解决 URI 模板的所有限制,因此已将其删除。本节将在即将发布的草案中进行重大更改,以用综合解决方案替换旧的预处理。
“href”的值将用作 URI 模板,如 RFC 6570 [RFC6570] 中定义的那样。但是,有一些特殊注意事项适用
URI 模板使用来自外部来源和实例的某些组合的数据进行填充。在可以使用实例数据或用户代理数据的情况下,本节将简单地引用“数据”或“值”。当来源很重要时,会明确指定。为了允许使用任何对象属性(包括空字符串)或数组索引,定义了以下规则
对于 URI 模板中的给定变量名称,使用以下方式确定要使用的值
如果存在 "hrefSchema" [hrefSchema] 并且提供了用户代理数据,则数据必须根据“hrefSchema”的值是有效的实例。模板变量,在上述过程之后,必须首先从用户代理数据实例解析。任何未解析的变量必须从资源实例数据解析。
当 URI 模板引用的任何值为空、布尔值或数字时,应首先将其转换为字符串,如下所示
在某些软件环境中,数字的原始 JSON 表示将不可用(无法区分 1.0 和 1),因此应使用任何合理的表示。模式和 API 作者应牢记这一点,如果精确表示很重要,则使用其他类型(例如字符串或布尔值)。
有时,适当的值将不可用。例如,模板可能指定使用对象属性,但没有提供此类数据(或“hrefSchema”不存在),并且实例是数组或字符串。
如果模板所需的值既不存在于用户代理数据(如果相关)中,也不存在于 JSON 实例中,则可以从其他来源(例如默认值)提供替换值。否则,应认为链接定义不适用于该实例。
“hrefSchema”链接描述属性的值必须是有效的 JSON 模式。此模式用于验证用户输入或其他用户代理数据,以填充 "href" [href] 中的 URI 模板,如该部分所述。
省略“hrefSchema”或将整个模式设置为“false”会阻止接受任何用户代理数据。
实现不得尝试使用“hrefSchema”验证从资源实例数据解析的值。这允许对用户代理数据使用不同的验证规则,例如支持日期时间输入的拼写月份,但使用标准日期时间格式进行存储。
例如,这为 URI 模板中的每个查询字符串参数定义了一个模式
{ "href": "/foos{?condition,count,query}", "hrefSchema": { "properties": { "condition": { "type": "boolean", "default": true }, "count": { "type": "integer", "minimum": 0, "default": 0 }, "query": { "type": "string" } } } }
在此示例中,为“extra”指定的模式是作为对引用进行的引用,以使用户代理数据验证约束与实例验证约束对于相应属性保持一致,而“id”被指定了一个 false 模式,以阻止该变量的用户代理数据。
{ "definitions": { "extra": { "type": "string", "maxLength": 32 } }, "type": "object", "properties": { "id": { "type": "integer", "minimum": 1, "readOnly": true }, "extra": {"$ref": "#/definitions/extra"} }, "links": [{ "rel": "self", "href": "/things/{id}{?extra}", "hrefSchema": { "properties": { "id": false, "extra": {"$ref": "#/definitions/extra"} } } }] }
[CREF4]上面的示例通过使用新的“hrefSchema”关键字来模拟早期草案中使用“method”为“get”处理的行为。
“rel”属性的值指示与目标资源的关系名称。该值必须是 RFC 5988 中建立的 IANA 链接关系类型注册表 [RFC5988] 中注册的链接关系,或遵循 RFC 3986 的 URI 生成 [RFC3986] 的规范化 URI。
与目标的关系被解释为来自模式(或子模式)适用的实例,而不是实例可能发现的任何较大的文档。
关系定义通常不依赖于媒体类型,鼓励用户使用现有的已接受关系定义。
例如,如果定义了一个超模式
{ "type": "array", "items": { "links": [{ "rel": "item", "href": "{id}" }, { "rel": "up", "href": "{upId}" }] } }
如果使用 JSON 表示检索了一组实例资源
GET /Resource/ [{ "id": "thing", "upId": "parent" }, { "id": "thing2", "upId": "parent" }]
这将表明,对于集合中的第一个项目,它自己的资源的 URI 将解析为“/Resource/thing”,并且第一个项目的“up”关系应解析为“/Resource/parent”处的资源。
请注意,这些关系值不区分大小写,与它们在 HTML 和 HTTP Link 标头 [RFC5988] 中的使用方式一致。
当使用“self”的链接关系来表示对象的完整表示时,如果目标 URI 不等同于或不是用于请求包含带有“self”链接的目标 URI 的资源表示的 URI 的子路径,则用户代理不应认为该表示是目标 URI 所表示的资源的权威表示。
例如,如果定义了一个超模式
{ "links": [{ "rel": "self", "href": "{id}" }] }
并且从 somesite.com 请求了一个资源
GET /foo/
响应为(添加了换行符和空格)
Content-Type: application/json; profile="http://example.com/alpha" [{ "id": "bar", "name": "This representation can be safely treated as authoritative " }, { "id": "/baz", "name": "This representation should not be treated as authoritative the user agent should make request the resource from '/baz' to ensure it has the authoritative representation" }, { "id": "http://othersite.com/something", "name": "This representation should also not be treated as authoritative and the target resource representation should be retrieved for the authoritative representation" }]
此属性为链接定义一个标题。该值必须是字符串。
用户代理可以在向用户显示链接时使用此标题。
此属性提供了一个模式,该模式预期用于描述链接目标的表示。根据协议,模式可能会也可能不会描述发送到链接的任何特定请求的响应。此属性仅供参考。
资源表示与 HTTP 请求和响应之间的关系由 RFC 7231,第 4.3.1 节 -“GET”,第 4.3.4 节“PUT”和第 3.1.4.2 节,“Content-Location” [RFC7231] 确定。特别是,“targetSchema”建议了客户端对 HTTP GET 的响应以及对“Content-Location”标头等于请求 URI 的任何响应可以期待什么,以及客户端在 HTTP PUT 请求中替换资源时应发送什么。根据 RFC 5789 [RFC5789],HTTP PATCH 的请求结构由“targetSchema”和请求媒体类型的组合确定。
此属性与“mediaType”具有类似的安全问题。客户端不得使用此属性的值来帮助解释接收到的数据以响应链接的跟踪,因为这会使“安全”数据容易受到重新解释的影响。
例如,假设两位程序员正在使用纯文本消息板讨论网络安全。以下是该对话中的一些数据,URI 为:http://forum.example.com/topics/152/comments/13
{ "topicId": 152, "commentId": 13, "from": { "name": "Jane", "id": 5 }, "to": { "name": "Jason", "id": 8 }, "message": "It's easy, just add some HTML like this: <script>doSomethingEvil()</script>" }
消息字符串被拆分为两行以提高可读性。
{ "rel": "evil-attack", "href": "http://forum.example.com/topics/152/comments/13", "targetSchema": { "properties": { "message": { "description": "Re-interpret `message` as HTML", "media": { "type": "text/html" } } } } }
然后,第三方可能会在另一个位置提供以下链接描述对象
如果客户端在解释上述数据时使用此“targetSchema”值,则它可能会将“message”的内容显示为 HTML。此时,消息中嵌入的 JavaScript 可能会被执行(在“forum.example.com”域的上下文中)。
此属性的值仅供参考,表示预期在获取此资源时返回的媒体类型 RFC 2046 [RFC2046]。此属性值也可能是一个媒体范围,使用与 RFC 7231,第 5.3.2 节 - HTTP "Accept" 标头 [RFC7231] 中定义的相同模式。
此属性类似于 HTML 中 <a> 元素的 "type" 属性(建议内容类型),或 HTTP Link 标头 [RFC5988] 中的 "type" 参数。用户代理可以使用此信息在遵循链接之前告知其向用户呈现的界面,但此信息绝不能在解释结果数据时使用此信息。在决定如何解释通过遵循此链接获得的数据时,用户代理的行为必须与该属性的值无关。
如果指定了此属性的值,并且链接的目标是使用支持 HTTP/1.1 "Accept" 标头的任何协议获取的 RFC 7231,第 5.3.2 节 [RFC7231],那么用户代理可以使用此属性的值来帮助组装向服务器发出请求时的该标头。
如果未指定此属性的值,则该值应视为 "application/json"。
例如,如果定义了模式
{ "links": [{ "rel": "self", "href": "/{id}/json" }, { "rel": "alternate", "href": "/{id}/html", "mediaType": "text/html" }, { "rel": "alternate", "href": "/{id}/rss", "mediaType": "application/rss+xml" }, { "rel": "icon", "href": "{id}/icon", "mediaType": "image/*" }] }
此模式描述的适当实例将定义四个链接。具有 "rel" 值为 "self" 的链接将具有预期的 MIME 类型 "application/json"(默认值)。具有 "rel" 值为 "alternate" 的两个链接指定了当前项目的 HTML 和 RSS 版本的位置。具有 "rel" 值为 "icon" 的链接链接到图像,但未指定确切格式。
显示上述示例中项目的视觉用户代理可能会呈现一个表示 RSS 提要的按钮,当按下该按钮时,它会将目标 URI(计算的 "href" 值)传递给更适合显示它的视图,例如新闻提要聚合器选项卡。
请注意,以上述方式呈现链接或将 URI 传递给新闻提要聚合器视图并不构成对数据的解释,而是对链接的解释。数据本身的解释由新闻提要聚合器执行,它应该拒绝任何不会也被解释为新闻提要的数据,即使它在主视图中显示。
链接定义中的 "mediaType" 属性定义了链接目标的预期格式。但是,这仅仅是建议性的,不应被视为权威性的。
在选择如何解释数据时,服务器提供的类型信息(或从文件名推断,或任何其他通常方法)必须是唯一考虑因素,并且链接的 "mediaType" 属性不得使用。用户代理可以使用此信息来确定如何表示链接或在何处显示它(例如悬停文本,在新标签页中打开)。如果用户代理决定将链接传递给外部程序,他们应该首先验证数据是否是通常传递给该外部程序的类型。
这是为了防止对 "安全" 数据的重新解释,类似于 "targetSchema" 的预防措施。
如果存在,此属性指示客户端应使用哪种媒体类型格式来表示由 "submissionSchema" [submissionSchema] 描述的请求有效负载。
省略此关键字与 "application/json" 值的行为相同。
请注意,"submissionEncType" 和 "submissionSchema" 不限于 HTTP URI。
例如,此链接指示如果您想向上下文资源的作者发送电子邮件,您的客户端需要同时请求纯文本和 HTML 表示。
{ "links": [{ "submissionEncType": "multipart/alternative; boundary=ab12", "rel": "author", "href": "mailto:[email protected]{?subject}", "hrefSchema": { "type": "object", "properties": { "subject": { "type": "string" } }, "required": ["subject"] }, "submissionSchema": { "type": "array", "items": [ { "type": "string", "media": { "type": "text/plain; charset=utf8" } }, { "type": "string", "media": { "type": "text/html" } } ], "minItems": 2 } }] }
此属性包含一个模式,该模式定义了要根据 "submissionEncType" 属性进行编码并发送到目标资源以进行处理的文档的可接受结构。这可以被视为描述由目标资源实现的处理函数的域。
这是一个与 "targetSchema" [targetSchema] 属性不同的概念,后者描述的是目标信息资源(包括在 PUT 请求中替换资源的内容),而 "submissionSchema" 则描述了要由资源评估的用户提交的请求数据。"submissionSchema" 旨在用于具有未根据目标表示定义的有效负载的请求。
省略 "submissionSchema" 或将整个模式设置为 "false" 将阻止任何用户代理数据被接受。
[RFC2045] | Freed, N. 和 N. Borenstein,"多用途互联网邮件扩展 (MIME) 第一部分:互联网消息正文的格式",RFC 2045,DOI 10.17487/RFC2045,1996 年 11 月。 |
[RFC2119] | Bradner, S.,"用于 RFC 中指示需求级别的关键词",BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。 |
[RFC3986] | Berners-Lee, T.,Fielding, R. 和 L. Masinter,"统一资源标识符 (URI):通用语法",STD 66,RFC 3986,DOI 10.17487/RFC3986,2005 年 1 月。 |
[RFC6570] | Gregorio, J.,Fielding, R.,Hadley, M.,Nottingham, M. 和 D. Orchard,"URI 模板",RFC 6570,DOI 10.17487/RFC6570,2012 年 3 月。 |
[json-schema] | Wright, A.,"JSON 模式:描述 JSON 文档的媒体类型",互联网草案 draft-wright-json-schema-00,2016 年 10 月。 |
[RFC2046] | Freed, N. 和 N. Borenstein,"多用途互联网邮件扩展 (MIME) 第二部分:媒体类型",RFC 2046,DOI 10.17487/RFC2046,1996 年 11 月。 |
[RFC5789] | Dusseault, L. 和 J. Snell,"HTTP 的 PATCH 方法",RFC 5789,DOI 10.17487/RFC5789,2010 年 3 月。 |
[RFC5988] | Nottingham, M.,"网络链接",RFC 5988,DOI 10.17487/RFC5988,2010 年 10 月。 |
[RFC7231] | Fielding, R. 和 J. Reschke,"超文本传输协议 (HTTP/1.1):语义和内容",RFC 7231,DOI 10.17487/RFC7231,2014 年 6 月。 |
感谢 Gary Court、Francis Galiegue、Kris Zyp 和 Geraint Luff 对 JSON 模式初稿的贡献。
感谢 Jason Desrosiers、Daniel Perrett、Erik Wilde、Ben Hutton、Evgeny Poberezkin、Brad Bowman、Gowry Sankar、Donald Pipowitch、Dave Finlay 和 Denis Laxalde 对文档的提交和修补。