互联网工程任务组 | G. Luff,编辑 |
互联网草案 | |
预期状态:信息性 | K. Zyp |
过期时间:2017 年 8 月 26 日 | SitePen(美国) |
G. Court | |
2013 |
JSON 超级模式:JSON 模式超文本定义
draft-luff-json-hyper-schema-00
JSON 模式是一种基于 JSON 的格式,用于定义 JSON 数据的结构。本文档指定了 JSON 模式的超链接和超媒体相关关键字。
本互联网草案完全符合 BCP 78 和 BCP 79 的规定提交。
互联网草案是互联网工程任务组 (IETF) 的工作文档。请注意,其他团体也可能以互联网草案的形式分发工作文档。当前互联网草案的列表位于 http://datatracker.ietf.org/drafts/current/。
互联网草案是有效期最长为六个月的草案文档,可能随时被更新、替换或被其他文档废弃。不应将互联网草案用作参考资料或引用,除非是“正在进行的工作”。
本互联网草案将于 2017 年 8 月 26 日过期。
版权所有 (c) 2013 IETF 信托基金会和被识别为文档作者的人员。保留所有权利。
本文件受 BCP 78 和 IETF 信托基金会关于 IETF 文档的法律条款 (http://trustee.ietf.org/license-info) 的约束,这些条款在发布本文件之日生效。请仔细阅读这些文档,因为它们描述了您对本文件的权利和限制。从本文件中提取的代码组件必须包含简化的 BSD 许可证文本,如信托法律条款的第 4.e 节所述,并且按简化的 BSD 许可证的描述提供,不提供任何保证。
JSON 模式是一种基于 JSON 的格式,用于定义 JSON 数据的结构。本文档指定了 JSON 模式的超链接和超媒体相关关键字。
术语“JSON 超级模式”用于指代使用这些关键字的 JSON 模式。
本规范将使用 JSON 模式核心规范 [json-schema-core] 中定义的术语。建议读者有一份该规范的副本。
本文档中的关键术语“必须”、“不得”、“必需”、“应”、“不应”、“建议”、“不建议”、“可选”和“可选”应按 RFC 2119 [RFC2119] 中的描述进行解释。
术语“模式”、“实例”、“属性”和“项目”应按 JSON 模式核心规范 [json-schema-core] 中的定义进行解释。
本文档描述了如何使用 JSON 模式在实例数据上定义超链接。它还定义了如何提供解释 JSON 数据为丰富的多媒体文档所需的其他信息。
与核心 JSON 模式关键字一样,“模式关键字”部分中描述的所有关键字都是可选的。
以下是一个使用超链接定义 JSON 模式,并为“imgData”属性提供多媒体解释的示例。
{ "title": "Written Article", "type": "object", "properties": { "id": { "title": "Article Identifier", "type": "number" }, "title": { "title": "Article Title", "type": "string" }, "authorId": { "type": "integer" }, "imgData": { "title": "Article Illustration (small)", "type": "string", "media": { "binaryEncoding": "base64", "type": "image/png" } } }, "required" : ["id", "title", "authorId"], "links": [ { "rel": "full", "href": "{id}" }, { "rel": "author", "href": "/user?id={authorId}" } ] }
此示例模式定义了实例的属性。对于“imgData”属性,它指定它应该被 Base64 解码,并将生成的二进制数据视为 PNG 图像。它还为实例定义了链接关系,其 URI 包含来自实例的值。
由上述模式描述的 JSON 实例的示例可能是
{ "id": 15, "title": "Example data", "authorId": 105, "imgData": "iVBORw...kJggg==" }
为了便于阅读,Base64 数据已被简化。
本文档的目的是为 JSON 模式定义关键字,使 JSON 数据能够被理解为超文本。
JSON 数据本身需要客户端对格式有特殊了解才能被解释为超文本。本文档提出了一种在不定义保留关键字或限制 JSON 数据结构的情况下,描述此类 JSON 格式的超文本和超媒体解释的方法。
模式的“links”属性用于将链接描述对象与实例关联。此属性的值必须是一个数组,数组中的项目必须是链接描述对象,如下所述。
使用“links”关键字的示例模式可能是
{ "title": "Schema defining links", "links": [ { "rel": "full", "href": "{id}" }, { "rel": "parent", "href": "{parent}" } ] }
单个 URI 可能会与实例有多个角色关系。这不是问题——同一个 URI 可以用于多个链接描述对象中。
例如,此模式描述了通过 HTTP 访问的博客文章的格式。链接描述了如何访问文章的评论,如何搜索评论,以及如何提交新评论,所有这些都使用同一个 URI。
{ "title": "News post", ... "links": [ { "rel": "comments", "href": "/{id}/comments" }, { "rel": "search", "href": "/{id}/comments", "schema": { "type": "object", "properties": { "searchTerm": { "type": "string" }, "itemsPerPage": { "type": "integer", "minimum": 10, "multipleOf": 10, "default": 20 } }, "required": ["searchTerm"] } }, { "title": "Post a comment", "rel": "create", "href": "/{id}/comments", "method": "POST", "schema": { "type": "object", "properties": { "message": { "type": "string" } }, "required": ["message"] } } ] }
如果客户端遵循第一个链接,则 URI 可能会扩展为“/15/comments”。对于第二个链接,方法为“GET”(HTTP 的默认方法),因此遵循此链接的客户端会将参数添加到 URL 中,生成类似于“/15/comments?searchTerm=JSON&itemsPerPage=50”的内容。第三个链接定义了一个可能的交互,其中客户端会向 URI(例如“/15/comments”)发出 POST 请求,其中 POST 数据是新评论的 JSON 表示形式,例如
{ "message": "This is an example comment" }
当寻址 JSON 文档时,URI 的片段部分可用于引用文档中的特定实例。
此关键字指示在给定片段部分的情况下,用于在文档中查找适当实例的方法。默认的片段解析协议为“json-pointer”,它将在下面定义。其他片段解析协议可以使用,但本文档中没有定义。
如果实例由提供具有“root”关系的链接的模式描述,或者使用 HTTP 链接头 [RFC5988] 提供了此类链接,则“root”链接的目标应被视为所有使用文档结构的片段解析方法(例如“json-pointer”)的文档根。对此的唯一例外是“root”链接本身的解析。
“json-pointer”片段解析协议使用 JSON 指针 [json-pointer] 来解析实例表示形式中 URI 中的片段标识符。
“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": { "mediaType": "text/html" } }
由此模式描述的实例应为包含 HTML 的字符串,使用 JSON 字符串解码成的任何字符集(默认值为 Unicode)。
如果其值为布尔值 true,则此关键字指示不应更改实例属性,并且预计用户代理尝试修改此属性的值会被服务器拒绝。
此关键字的值必须是布尔值。默认值为 false。
此属性是一个 URI,它定义了为了验证,实例的 URI 必须以什么开头。 “pathStart”属性的值必须使用 RFC 3986,第 5 节 [RFC3986] 中的规则,相对于最近的 URI 解析范围(如 JSON 模式核心规范 [json-schema-core] 中所定义)进行解析。
当为实例引用了多个模式时,用户代理可以通过确定实例的 URI 是否以“pathStart”属性的值开头来确定此模式是否适用于特定实例。如果实例的 URI 不以此 URI 开头,或者另一个模式指定了一个更长且也与实例匹配的起始 URI,则不应将此模式视为描述实例。任何没有 pathStart 属性的模式都应被视为适用于其被引用的所有实例。
链接描述对象 (LDO) 用于描述单个链接关系。在模式的上下文中,它定义了模式实例的链接关系,并且可以通过实例值进行参数化。链接描述对象 (LDO) 必须是一个对象。
链接描述格式可以在没有 JSON 模式的情况下使用,并且可以通过将规范的链接描述模式引用为使用链接的数据结构的模式来声明此格式的使用。规范链接描述模式的 URI 为: https://json-schema.fullstack.org.cn/links(最新版本)或 https://json-schema.fullstack.org.cn/draft-04/links(draft-04 版本)。
"表单" 式功能可以通过使用 "schema" 关键字来定义,它提供了一个描述要提供给服务器的数据的模式。
"href" 链接描述属性的值是一个模板,用于确定相关资源的目标 URI。实例属性的值 SHOULD 被解析为一个 URI-Reference,根据 RFC 3986 [RFC3986],并且 MAY 是对 URI 的相对引用。用于相对 URI 解析的基 URI SHOULD 是用于检索实例对象的 URI(而不是模式)。
用于相对 URI 解析的基 URI SHOULD 定义如下
此属性不是可选的。
"href" 的值将用作 URI 模板,如 RFC 6570 [RFC6570] 中所定义。但是,有一些特殊情况需要考虑
URI 模板规范 [RFC6570] 限制了可用于变量名的字符集。但是,JSON 中的属性名可以是任何 UTF-8 字符串。
为了允许在模板中使用任何 JSON 属性名,在将 "href" 的值用作 URI 模板之前,MUST 按顺序应用以下预处理规则
此步骤的目的是允许在花括号内使用括号来对变量名进行百分比编码。要转义的变量名用圆括号括起来,其中右圆括号字符 ")" 被转义为一对右圆括号 "))"。由于空字符串在 RFC 6570 中不是有效的变量名,因此一对空括号将被替换为 "%65mpty"。
规则如下
找到文本中尽可能大的部分,使其
文本中的每个部分(包括周围的圆括号)MUST 根据以下规则进行替换
在进行上述替换后,如果字符 "$"(美元符号)出现在一对花括号内,那么 MUST 将其替换为文本 "%73elf"(即 "self",其中 "s" 被百分比编码)。
此阶段的目的是允许通过特殊值 "%73elf" 在 URI 模板中使用实例值本身(而不是其对象属性或数组项)。
特殊情况值 "%73elf" 和 "%65mpty" 的选择是因为它们不太可能被人类或自动化转义意外生成。
例如,以下是一些 "href" 的可能值,以及预处理后的结果
{% raw %} Input Output ----------------------------------------- "no change" "no change" "(no change)" "(no change)" "{(escape space)}" "{escape%20space}" "{(escape+plus)}" "{escape%2Bplus}" "{(escape*asterisk)}" "{escape%2Aasterisk}" "{(escape(bracket)}" "{escape%28bracket}" "{(escape))bracket)}" "{escape%29bracket}" "{(a))b)}" "{a%29b} "{(a (b)))}" "{a%20%28b%29} "{()}" "{%65mpty} "{+$*}" "{+%73elf*} "{+($)*}" "{+%24*} {% endraw %}
请注意,在最后一个示例中,由于 "+" 位于括号之外,因此它保持未转义,而在第四个示例中,"+" 被转义了。
预处理后,将使用来自实例的数据填写 URI 模板。为了允许使用任何对象属性(包括空字符串)、数组索引或实例值本身,定义了以下规则
对于 URI 模板中给定的变量名,将使用以下规则确定要使用的值
当 URI 模板引用的任何值为 null、布尔值或数字时,应首先将其转换为字符串,方法如下
在某些软件环境中,数字的原始 JSON 表示形式将不可用(无法区分 1.0 和 1),因此应使用任何合理的表示形式。模式和 API 作者应牢记这一点,如果确切的表示形式很重要,则应使用其他类型(如字符串或布尔值)。
有时,合适的 value 将不可用。例如,模板可能指定使用对象属性,但实例是数组或字符串。
如果模板所需的任何值在 JSON 实例中不存在,那么 MAY 从其他来源(如默认值)提供替代值。否则,SHOULD 认为链接定义不适用于该实例。
"rel" 属性的值表示与目标资源的关系的名称。此属性不是可选的。
与目标的关系 SHOULD 被解释为特别地来自模式(或子模式)适用的实例对象,而不仅仅是包含该对象的层次结构中的顶级资源。来自顶级资源到目标的链接关系 MUST 使用描述顶级 JSON 表示形式的模式来指示。
关系定义 SHOULD NOT 依赖于媒体类型,并且鼓励用户利用现有的已接受的关系定义,包括现有关系注册表中的定义(参见 RFC 4287 [RFC4287])。但是,为了在 JSON 模式定义的关系的上下文中明确解释规范性解释,我们在这里定义了这些关系
如果模式需要与来自实例的数据进行参数化,则以下关系适用于模式(模式作为关系中的 "from" 资源)
例如,如果定义了一个模式
{ "links": [{ "rel": "self", "href": "{id}" }, { "rel": "up", "href": "{upId}" }, { "rel": "children", "href": "?upId={id}" }] }
如果使用 JSON 表示形式检索实例资源的集合
GET /Resource/ [{ "id": "thing", "upId": "parent" }, { "id": "thing2", "upId": "parent" }]
这将表明对于集合中的第一个项目,其自身的(self)URI 将解析为 "/Resource/thing",并且第一个项目的 "up" 关系 SHOULD 解析为 "/Resource/parent" 处的资源。 "children" 集合将位于 "/Resource/?upId=thing" 处。
请注意,这些关系值不区分大小写,与它们在 HTML 和 HTTP Link header [RFC5988] 中的使用方式一致。
存在关系为 "root" 的链接会改变文档的根的定义。对于遍历文档的片段解析方法(如 JSON 指针片段),"root" 链接的目标应该是这些方法的起点。
唯一的例外是 "root" 链接本身。当计算关系为 "root" 的链接的目标时,MUST NOT 考虑现有的 "root" 链接。
例如,假设我们有以下模式
{ "links": [{ "rel": "root", "href": "#/myRootData" }] }
以及从 URI: "http://example.com/data/12345" 返回的以下数据
{ "myRootData": { "title": "Document title" }, "metaData": { ... } }
URI Data ----------------------------------------------------------------------- http://example.com/data/12345 {"title": "Document title"} http://example.com/data/12345#/title "Document title"
为了正确解析 URL "http://example.com/data/12345",我们必须考虑 "root" 链接。以下是带有一些示例 URI,以及它们将解析到的数据
当使用关系为 "self" 的链接来表示对象的完整表示形式时,如果目标 URI 不等效于或不是包含具有 "self" 链接的目标 URI 的资源表示形式的请求 URI 的子路径,则用户代理 SHOULD NOT 认为该表示形式是目标 URI 所表示资源的权威表示形式。
例如,如果定义了一个超模式
{ "links": [{ "rel": "self", "href": "{id}" }] }
并且从 somesite.com 请求了一个资源
GET /foo/
其响应为
Content-Type: application/json; profile=/schema-for-this-data [{ "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" }]
此属性为链接定义了一个标题。该值必须是字符串。
用户代理 MAY 在向用户展示链接时使用此标题。
此属性值仅供参考,是一个模式,如果使用 JSON 表示形式返回链接的目标,则它定义了链接目标的 JSON 表示形式的预期结构。
此属性与 "mediaType" 具有类似的安全问题。客户端 MUST NOT 使用此属性的值来帮助解释对链接的响应而接收到的数据,因为这会使 "安全" 数据容易受到重新解释。
例如,假设两个程序员正在使用纯文本留言板讨论网络安全。以下是来自该对话的一些数据,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, you 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 the message text as HTML", "media": { "type": "text/html" } } } } }
然后,第三方可以在其他位置提供以下链接描述对象
如果客户端在解释上述数据时使用此 "targetSchema" 值,那么它可能会将 "message" 的内容显示为 HTML。此时,消息中嵌入的 JavaScript 可能会执行(在 "forum.example.com" 域的上下文中)。
此属性的值仅供参考,表示预期在获取此资源时返回的媒体类型 RFC 2046 [RFC2046]。此属性值 MAY 为媒体范围,使用 RFC 2161,第 14.1 节 - HTTP "Accept" 头 [RFC2616] 中定义的相同模式。
此属性类似于 HTML 中 <a> 元素的 "type" 属性(建议的内容类型),或 HTTP 链接头 [RFC5988] 中的 "type" 参数。用户代理 MAY 使用此信息来告知他们在遵循链接之前向用户呈现的界面,但此信息 MUST NOT 在解释结果数据时使用此信息。在决定如何解释通过遵循此链接获得的数据时,用户代理的行为 MUST 相同,无论此属性的值如何。
如果指定了此属性的值,并且链接的目标是使用支持 HTTP/1.1 "Accept" 头的任何协议来获取 RFC 2616,第 14.1 节 [RFC2616],那么用户代理 MAY 使用此属性的值来帮助在向服务器发出请求时组装该头。
如果未指定此属性的值,则该值应被认为是 "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" 的链接将具有 "application/json"(默认值)的预期 MIME 类型。两个具有 "rel" 值为 "alternate" 的链接指定了当前项目 HTML 和 RSS 版本的位置。具有 "rel" 值为 "icon" 的链接链接到图像,但未指定确切格式。
显示上述示例中项目的视觉用户代理可能会呈现一个代表 RSS 提要的按钮,当按下该按钮时,它会将目标 URI(计算的 "href" 值)传递给更适合显示它的视图,例如新闻提要聚合器选项卡。
请注意,以上述方式呈现链接,或将 URI 传递给新闻提要聚合器视图,不构成对数据的解释,而是对链接的解释。数据本身的解释是由新闻提要聚合器执行的,它 SHOULD 拒绝任何本不应该被解释为新闻提要的数据,如果它在主视图中显示。
链接定义中的 "mediaType" 属性定义了链接目标的预期格式。但是,这仅供参考,MUST NOT 被视为权威性。
在选择如何解释数据时,服务器提供的信息类型(或从文件名推断,或任何其他常用方法) MUST 是唯一考虑因素,并且链接的 "mediaType" 属性 MUST NOT 使用。用户代理 MAY 使用此信息来确定他们如何表示链接或在哪里显示链接(例如悬停文本,在新标签页中打开)。如果用户代理决定将链接传递给外部程序,他们 SHOULD 首先验证数据是否属于通常传递给该外部程序的类型。
这是为了防止对 "安全" 数据的重新解释,类似于 "targetSchema" 的预防措施。
以下属性也适用于链接描述对象,并提供类似于 HTML 表单的功能,以便提供一种提交要发送到服务器的额外信息(通常是用户提供的)的方法。
此属性定义了哪些方法可用于访问目标资源。在 HTTP 环境中,这可能是 "GET" 或 "POST"(或其他 HTTP 方法)。
某些链接关系值暗示了一组适合用于该链接的 HTTP 方法。例如,客户端可能会假设具有 "edit" 关系的链接可以与 "PUT" HTTP 方法结合使用。如果客户端不知道哪些方法可能是合适的,那么这 SHOULD 默认使用 "GET"。
如果存在,此属性表示服务器支持的查询媒体类型格式,用于查询或发布到目标资源处的实例集合。查询可以附加到目标 URI 以查询集合,其中包含对服务器 SHOULD 返回的资源的基于属性的约束,或用于将数据发布到资源(取决于方法)。
例如,使用以下模式
{ "links": [{ "encType": "application/x-www-form-urlencoded", "method": "GET", "href": "/Product/", "properties": { "name": { "description": "name of the product" } } }] }
这表示客户端可以查询服务器以获取具有特定名称的实例。
例如
/Product/?name=Slinky
此属性包含一个模式,该模式定义了提交请求的可接受结构。对于 GET 请求,此模式将定义查询字符串的属性,而对于 POST 请求,这将定义主体。
请注意,这与 "href" 的 URI 模板化是分开的(后者使用来自实例的数据,而不是用户提交的数据)。它也与 "targetSchema" 属性是分开的,"targetSchema" 属性提供了客户端在遵循链接时应期望返回的数据的模式。
此注册表由 IANA 维护,根据 RFC 4287 [RFC4287] 和本规范添加了四个值:"full"、"create"、"instances"、"root"。新分配受 IESG 批准,如 RFC 5226 [RFC5226] 中所述。请求应通过电子邮件发送给 IANA,IANA 将转发请求给 IESG,请求批准。
[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 月。 |
[RFC4287] | Nottingham, M. 和 R. Sayre,“Atom 联合格式”,RFC 4287,DOI 10.17487/RFC4287,2005 年 12 月。 |
[RFC6570] | Gregorio, J.、Fielding, R.、Hadley, M.、Nottingham, M. 和 D. Orchard,“URI 模板”,RFC 6570,DOI 10.17487/RFC6570,2012 年 3 月。 |
[json-pointer] | Bryan, P.、Zyp, K. 和 M. Nottingham,“JSON 指针”,2012 年 8 月。 |
[json-schema-core] | Galiegue, F.、Zyp, K. 和 G. Court,“JSON 模式:核心定义和术语”,2013 年。 |
[RFC2616] | Fielding, R.、Gettys, J.、Mogul, J.、Frystyk, H.、Masinter, L.、Leach, P. 和 T. Berners-Lee,“超文本传输协议 - HTTP/1.1”,RFC 2616,DOI 10.17487/RFC2616,1999 年 6 月。 |
[RFC5226] | Narten, T. 和 H. Alvestrand,“在 RFC 中编写 IANA 注意事项部分的指南”,BCP 26,RFC 5226,DOI 10.17487/RFC5226,2008 年 5 月。 |
[RFC2046] | Freed, N. 和 N. Borenstein,“多用途互联网邮件扩展 (MIME) 第二部份:媒体类型”,RFC 2046,DOI 10.17487/RFC2046,1996 年 11 月。 |
[RFC5988] | Nottingham, M.,“网络链接”,RFC 5988,DOI 10.17487/RFC5988,2010 年 10 月。 |
[W3C.REC-html401-19991224] | Raggett, D.、Hors, A. 和 I. Jacobs,“HTML 4.01 规范”,万维网联盟建议 REC-html401-19991224,1999 年 12 月。 |