網際網路工程任務組 A. Wright, 編
網路草案
預定狀態:資訊性 H. Andrews, 編
截止日期:2017 年 10 月 23 日 Cloudflare, Inc.
2017 年 4 月 21 日

JSON Schema:描述 JSON 文件的媒體類型
draft-wright-json-schema-01

摘要

JSON Schema 定義了媒體類型「application/schema+json」,這是一種基於 JSON 的格式,用於描述 JSON 資料的結構。JSON Schema 會宣告 JSON 文件必須具備的外觀、從中擷取資訊的方式,以及與之互動的方式,非常適合用來註解現有的 JSON API,這些 API 本身可能沒有超媒體控制或機器可讀性。

讀者須知

此草案的問題列表可在 <https://github.com/json-schema-org/json-schema-spec/issues> 找到。

如需其他資訊,請參閱 <https://json-schema.dev.org.tw/>

如要提供意見回饋,請使用此問題追蹤器、首頁上列出的通訊方法,或以電子郵件聯絡文件編輯者。

本備忘錄的狀態

此網路草案的提交完全符合 BCP 78 和 BCP 79 的規定。

網路草案是網際網路工程任務組 (IETF) 的工作文件。請注意,其他群組也可能將工作文件作為網路草案發佈。目前網路草案的清單位於 http://datatracker.ietf.org/drafts/current/。

網路草案是有效期最長為六個月的草案文件,隨時可能被其他文件更新、取代或廢止。將網路草案用作參考資料,或將其引述為「進行中的工作」以外的其他用途是不恰當的。

此網路草案將於 2017 年 10 月 23 日到期。

著作權聲明

著作權 (c) 2017 IETF Trust 和被認定為文件作者的人士。保留所有權利。

本文件受 BCP 78 和 IETF Trust 關於 IETF 文件(http://trustee.ietf.org/license-info)的法律條款(於本文件發佈之日生效)的約束。請仔細閱讀這些文件,因為其中說明了您在本文件方面的權利和限制。從本文件中摘錄的程式碼組件必須包含信託法律條款第 4.e 節中所述的簡化 BSD 授權文字,並按簡化 BSD 授權中所述的方式提供,不作任何擔保。


目錄

1. 簡介

JSON Schema 是一種用於定義 JSON 資料結構的 JSON 媒體類型。JSON Schema 的目的是定義 JSON 資料的驗證、文件、超連結導覽和互動控制。

此規格定義了 JSON Schema 的核心術語和機制,包括透過參考指向另一個 JSON Schema、取消參考 JSON Schema 參考,以及指定正在使用的詞彙。

其他規格定義了關於驗證、連結、註解、導覽和互動的宣告詞彙。

2. 慣例與術語

本文件中,「必須」(MUST)、「不得」(MUST NOT)、「必要」(REQUIRED)、「應」(SHALL)、「不應」(SHALL NOT)、「應該」(SHOULD)、「不應該」(SHOULD NOT)、「建議」(RECOMMENDED)、「可能」(MAY) 和「選擇性」(OPTIONAL) 等關鍵字應按照 RFC 2119 [RFC2119] 中所述的方式進行解釋。

本文件中,「JSON」、「JSON 文字」、「JSON 值」、「成員」、「元素」、「物件」、「陣列」、「數字」、「字串」、「布林值」、「true」、「false」和「null」等詞彙應按照 RFC 7159 [RFC7159] 中定義的方式進行解釋。

3. 概述

本文件提出新的媒體類型「application/schema+json」,用以識別用於描述 JSON 資料的 JSON Schema。JSON Schema 本身就是 JSON 文件。此規格及相關規格定義了允許作者以多種方式描述 JSON 資料的關鍵字。

3.1. 驗證

JSON Schema 描述 JSON 文件的結構(例如,必要的屬性和長度限制)。應用程式可以使用此資訊來驗證執行個體(檢查是否符合約束),或告知介面收集使用者輸入,使其滿足約束。

驗證行為和關鍵字在 另一份文件 [json-schema-validation] 中指定。

3.2. 超媒體和連結

JSON Hyper-Schema 描述 JSON 文件的超文字結構。這包括從執行個體到其他資源的連結關係、將執行個體解讀為多媒體資料,以及使用 API 所需的提交資料。

超綱要行為和關鍵字在 另一份文件 [json-hyper-schema] 中指定。

4. 定義

4.1. JSON 文件

JSON 文件是由 application/json 媒體類型描述的資訊資源(一系列八位元組)。

在 JSON Schema 中,「JSON 文件」、「JSON 文字」和「JSON 值」等詞彙可以互換使用,因為它們定義的資料模型相同。

JSON Schema 僅在 JSON 文件上定義。但是,任何可以根據 JSON Schema 資料模型剖析或處理的文件或記憶體結構,都可以根據 JSON Schema 進行解釋,包括 CBOR [RFC7049] 等媒體類型。

4.2. 執行個體

JSON Schema 會根據資料模型解讀文件。根據此資料模型解讀的 JSON 值稱為「執行個體」。

執行個體具有六種基本類型之一,以及根據類型而定的一系列可能值

null
JSON 「null」產生式
布林值
來自 JSON 「true」或「false」產生式的「true」或「false」值
物件
來自 JSON 「object」產生式的一組將字串對應到執行個體的無序屬性
陣列
來自 JSON 「array」產生式的一組執行個體的有序清單
數字
來自 JSON 「number」產生式的一個任意精確度的 10 進位數值
字串
來自 JSON 「string」產生式的一組 Unicode 字碼點

因此,空白和格式設定考量超出 JSON Schema 的範圍。

由於物件不能有兩個具有相同索引鍵的屬性,因此對於嘗試在單一物件中定義兩個具有相同索引鍵(「字串」產生式)的屬性(「成員」產生式)的 JSON 文件而言,其行為是未定義的。

4.3. 執行個體相等

當且僅當兩個 JSON 執行個體屬於相同類型且根據資料模型具有相同的值時,才會說它們相等。具體而言,這表示

此定義隱含著陣列的長度必須相同、物件必須具有相同數量的成員、物件中的屬性是無序的、無法定義具有相同索引鍵的多個屬性,而且單純的格式差異(縮排、逗號的位置、尾隨零)是無關緊要的。

4.4. JSON Schema 文件

JSON Schema 文件(或簡稱為綱要)是用於描述執行個體的 JSON 文件。綱要本身會解讀為執行個體。JSON Schema 必須是物件或布林值。

布林值等同於下列行為

true
一律通過驗證,如同空的綱要 {}
false
一律無法通過驗證,如同綱要 { "not":{} }

用於描述執行個體的屬性稱為關鍵字或綱要關鍵字。屬性的意義由綱要使用的詞彙指定。

JSON Schema 可能包含不是綱要關鍵字的屬性。未知的關鍵字應忽略。

本身描述綱要的綱要稱為中繼綱要。中繼綱用於驗證 JSON Schema 並指定其使用的詞彙。

空的綱要是沒有屬性或只有未知屬性的 JSON Schema。

4.5. 根綱要和子綱要

根綱要是包含相關 JSON 文件全部內容的綱要。

某些關鍵字本身會採用綱要,允許巢狀 JSON Schema

{
    "title": "root",
    "items": {
        "title": "array item"
    }
}

                    

在此範例文件中,標題為「array item」的綱要是子綱要,標題為「root」的綱要是根綱要。

與根綱要一樣,子綱要也是物件或布林值。

5. 片段識別符

根據 [RFC6839] 的第 3.1 節,為任何 +json 媒體類型指定的片段識別符的語法和語意應與為「application/json」指定的語法和語意相同。(在本文件發佈時,「application/json」沒有定義任何片段識別語法。)

此外,「application/schema+json」媒體類型支援兩種片段識別符結構:純名稱和 JSON 指標。在 RFC 6901 [RFC6901] 中描述了將 JSON 指標用作 URI 片段識別符的方式。符合 JSON 指標語法的片段識別符(包括空字串)必須解讀為 JSON 指標片段識別符。

根據 W3C 的片段識別符最佳做法 [W3C.WD-fragid-best-practices-20121025],純名稱片段識別符保留用於參考本機命名的綱要。所有不符合 JSON 指標語法的片段識別符都必須解讀為純名稱片段識別符。

「$id」關鍵字 [id-keyword] 章節中定義和參考純名稱片段識別符。

6. 一般考量

6.1. JSON 值的範圍

執行個體可能是 JSON [RFC7159] 定義的任何有效 JSON 值。JSON Schema 對類型沒有任何限制:JSON Schema 可以描述任何 JSON 值,包括 null。

6.2. 程式語言獨立性

JSON Schema 與程式語言無關,並支援資料模型中描述的完整數值範圍。然而,請注意,某些語言和 JSON 解析器可能無法在記憶體中表示 JSON 可描述的完整數值範圍。

6.3. 數學整數

某些程式語言和解析器對於浮點數和整數使用不同的內部表示方式。

為了保持一致性,整數 JSON 數字「不應」使用小數部分進行編碼。

6.4. 擴展 JSON Schema

實作可以為 JSON Schema 定義額外的關鍵字。除非有明確的協議,否則架構作者「不應」期望這些額外的關鍵字能被同級實作支援。實作「應」忽略它們不支援的關鍵字。

鼓勵 JSON Schema 擴展的作者編寫自己的元架構,使用 "allOf" 來擴展現有的元架構。這個擴展的元架構「應」使用 "$schema" 關鍵字來引用,以便工具可以遵循正確的行為。

7. "$schema" 關鍵字

"$schema" 關鍵字既用作 JSON Schema 版本識別符,也用作 JSON Schema 本身的資源位置,該 JSON Schema 描述了為此特定版本編寫的任何架構。

此關鍵字的值「必須」是 URI [RFC3986](包含方案),並且此 URI 「必須」被正規化。當前架構「必須」對照此 URI 識別的元架構有效。

"$schema" 關鍵字「應」在根架構中使用。它「不得」出現在子架構中。

[CREF1]雖然這種模式很可能仍然是架構撰寫的最佳實踐,但實作行為可能會在未來的草案中進行修改或放寬。

此屬性的值在其他文件中以及由其他方定義。JSON Schema 實作「應」實作對當前和先前發布的 JSON Schema 詞彙草案的支援,視為合理。

8. 使用 $ref 的架構參考

"$ref" 關鍵字用於參考架構,並提供透過自我參考來驗證遞迴結構的能力。

具有 "$ref" 屬性的物件架構「必須」被解釋為 "$ref" 參考。"$ref" 屬性的值「必須」是一個 URI 參考。相對於當前 URI 基礎解析後,它識別要使用的架構的 URI。"$ref" 物件中的所有其他屬性「必須」被忽略。

該 URI 不是網路定位器,而僅是識別符。如果架構是可網路定址的 URL,則不一定需要從該地址下載,並且實作「不應」假設它們在遇到可網路定址的 URI 時應執行網路操作。

架構「不得」陷入針對架構的無限迴圈。例如,如果兩個架構 "#alice" 和 "#bob" 都具有一個 "allOf" 屬性,該屬性引用另一個架構,則天真的驗證器可能會在嘗試驗證實例時陷入無限遞迴迴圈。架構「不應」使用像這樣的無限遞迴巢狀結構;其行為是未定義的。

9. 基礎 URI 和取消參考

9.1. 初始基礎 URI

RFC3986 第 5.1 節 [RFC3986] 定義了如何確定文件的預設基礎 URI。

資訊性地說,架構的初始基礎 URI 是找到它的 URI,或者如果沒有已知的 URI,則使用合適的替代 URI。

9.2. "$id" 關鍵字

"$id" 關鍵字定義架構的 URI,以及在架構內解析其他 URI 參考的基礎 URI。"$id" 關鍵字本身是針對物件整體所在的基礎 URI 進行解析的。

如果存在,此關鍵字的值「必須」是一個字串,並且「必須」表示有效的 URI 參考 [RFC3986]。此值「應」被正規化,並且「不應」是一個空的片段 <#> 或一個空字串 <>。

JSON Schema 文件的根架構「應」包含一個帶有 URI(包含方案)的 "$id" 關鍵字。此 URI「應」沒有片段,或者具有一個空字串的片段。[CREF2]如果 "$id" URI 參考包含具有其他元件的片段,應該如何解釋?有兩種情況:當其他元件與當前基礎 URI 匹配時,以及當它們更改基礎 URI 時。

為了在 JSON Schema 文件中命名子架構,子架構可以使用 "$id" 為自己提供一個文件本地識別符。這是透過將 "$id" 設置為僅由片段組成的 URI 參考來完成的。片段識別符「必須」以字母 ([A-Za-z]) 開頭,後跟任意數量的字母、數字 ([0-9])、連字符 ("-")、底線 ("_")、冒號 (":") 或句點 (".")。

定義一個既不符合上述要求也不是有效 JSON 指標的 "$id" 的效果是未定義的。

{
    "$id": "http://example.com/root.json",
    "definitions": {
        "A": { "$id": "#foo" },
        "B": {
            "$id": "other.json",
            "definitions": {
                "X": { "$id": "#bar" },
                "Y": { "$id": "t/inner.json" }
            }
        },
        "C": {
            "$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"
        }
    }
}

                        

例如

以下 URI 編碼的 JSON 指標 [RFC6901](相對於根架構)的架構具有以下基礎 URI,並且可以依照以上第 5 節中的任一 URI 來識別

#(文件根)
http://example.com/root.json#
#/definitions/A
http://example.com/root.json#foo
#/definitions/B
http://example.com/other.json
#/definitions/B/definitions/X
http://example.com/other.json#bar
#/definitions/B/definitions/Y
http://example.com/t/inner.json
#/definitions/C
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f

9.2.1. 內部參考

架構可以透過賦予它們的任何 URI 來識別,包括 JSON 指標或它們直接由 "$id" 給出的 URI。

工具「應」注意架構(包括子架構)使用 "$id" 為自己提供的 URI。這被稱為「內部參考」。

例如,考慮這個架構

{
    "$id": "http://example.net/root.json",
    "items": {
        "type": "array",
        "items": { "$ref": "#item" }
    },
    "definitions": {
        "single": {
            "$id": "#item",
            "type": "integer"
        }
    }
}

                        

當實作遇到 <#/definitions/single> 架構時,它會針對當前基礎 URI 解析 "$id" URI 參考,以形成 <http://example.net/root.json#item>。

當實作隨後查看 <#/items> 架構時,它會遇到 <#item> 參考,並將其解析為 <http://example.net/root.json#item>,這被理解為在同一文件中其他地方定義的架構。

9.2.2. 外部參考

為了在龐大的生態系統中區分彼此的架構,架構由 URI 識別。如上所述,這不一定表示會下載任何內容,而是 JSON Schema 實作「應」已經了解它們將要使用的架構,包括識別它們的 URI。

實作「應」能夠將任意 URI 與任意架構關聯,和/或根據驗證器對架構的信任程度,自動關聯架構的 "$id" 給定的 URI。

一個架構「可以」(並且很可能)有多個 URI,但是一個 URI 無法識別多個架構。當多個架構嘗試使用相同的 URI 識別時,驗證器「應」引發錯誤條件。

10. 超媒體的用法

JSON 已被 HTTP 伺服器廣泛採用於自動化 API 和機器人。本節描述如何在與支援媒體類型和 Web 連結 [RFC5988] 的協定一起使用時,以更 RESTful 的方式增強 JSON 文件的處理。

10.1. 連結到架構

建議由架構/配置檔案描述的實例使用 連結資料協定 1.0 第 8.1 節 [W3C.REC-ldp-20150226] 中定義的連結關係 "describedby",提供到可下載 JSON Schema 的連結。

在 HTTP 中,此類連結可以使用 Link 標頭 [RFC5988] 附加到任何回應。此類標頭的一個範例是

Link: <http://example.com/my-hyper-schema#>; rel="describedby"

                    

10.2. 描述 JSON 的配置檔案

實例「可以」按照 「配置檔案」連結關係 [RFC6906] 中所述指定「配置檔案」。當用作媒體類型參數時,HTTP 伺服器可以根據配置檔案執行 Content-Type 協商。媒體類型參數「必須」是一個以空格分隔的 URI 列表(即,相對參考無效)。

配置檔案 URI 是不透明的,並且「不應」自動取消參考。如果實作不了解所提供配置檔案的語義,則實作可以改為追蹤 "describedby" 連結(如果有的話),這可以提供有關如何處理配置檔案的資訊。由於「配置檔案」不一定指向網路位置,因此 "describedby" 關係用於連結到可下載的架構。但是,為了簡化起見,架構作者應盡可能使這些 URI 指向相同的資源。

在 HTTP 中,媒體類型參數將在 Content-Type 標頭中發送

Content-Type: application/json;
          profile="http://example.com/my-hyper-schema#"

                    

多個配置檔案以空格分隔

Content-Type: application/json;
          profile="http://example.com/alice http://example.com/bob"

                    

HTTP 也可以在連結中發送「配置檔案」,儘管如果這完全取代媒體類型參數,則可能會影響媒體類型語義和 Content-Type 協商

Link: </alice>;rel="profile", </bob>;rel="profile"

                    

10.3. 在 HTTP 上的用法

當用於網路上的超媒體系統時,HTTP [RFC7231] 通常是分發架構的首選協定。如果惡意用戶端過於頻繁地透過網路提取架構,則可能會給伺服器維護人員帶來問題,而實際上可以將架構快取一段較長的時間。

HTTP 伺服器「應」在 JSON Schema 上設定長期快取標頭。HTTP 用戶端「應」觀察快取標頭,並且在它們的有效期限內不重新請求文件。分散式系統「應」使用共用快取和/或快取 Proxy。

User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0

                        

用戶端「應」設定或前置特定於 JSON Schema 實作或軟體產品的 User-Agent 標頭。由於符號以重要性遞減的順序列出,因此 JSON Schema 程式庫名稱/版本應優先於較通用的 HTTP 程式庫名稱(如果有的話)。例如

用戶端「應」能夠使用 "From" 標頭發出請求,以便伺服器操作員可以聯繫潛在惡意腳本的所有者。

11. 安全性考量

架構和實例都是 JSON 值。因此,適用於 RFC 7159 [RFC7159] 中定義的所有安全性考量。

實例和架構通常都由不受信任的第三方編寫,以部署在公共網際網路伺服器上。驗證器應注意,解析架構不會消耗過多的系統資源。驗證器「不得」陷入無限迴圈。

伺服器需要注意,惡意方無法透過上傳具有預先存在的或非常相似的 "$id" 的架構來變更現有架構的功能。

個別 JSON Schema 詞彙也可能會有自己的安全性考量。有關更多資訊,請參閱各自的規格。

12. IANA 考量

JSON Schema 的擬議 MIME 媒體類型定義如下

13. 參考文獻

13.1. 規範性參考文獻

[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 月。
[RFC6839] Hansen, T.A. Melnikov, "附加媒體類型結構化語法後綴", RFC 6839, DOI 10.17487/RFC6839, 2013 年 1 月。
[RFC6901] Bryan, P.Zyp, K.M. Nottingham, "JavaScript 物件表示法 (JSON) 指標", RFC 6901, DOI 10.17487/RFC6901, 2013 年 4 月。
[RFC7159] Bray, T., "JavaScript 物件表示法 (JSON) 資料交換格式", RFC 7159, DOI 10.17487/RFC7159, 2014 年 3 月。
[W3C.REC-ldp-20150226] Speicher, S.Arwe, J.A. Malhotra, "連結資料平台 1.0", World Wide Web Consortium Recommendation REC-ldp-20150226, 2015 年 2 月。

13.2. 參考性參考文獻

[RFC5988] Nottingham, M., "網路連結", RFC 5988, DOI 10.17487/RFC5988, 2010 年 10 月。
[RFC6906] Wilde, E., "「設定檔」連結關係類型", RFC 6906, DOI 10.17487/RFC6906, 2013 年 3 月。
[RFC7049] Bormann, C.P. Hoffman, "簡潔二進位物件表示法 (CBOR)", RFC 7049, DOI 10.17487/RFC7049, 2013 年 10 月。
[RFC7231] Fielding, R.J. Reschke, "超文字傳輸協定 (HTTP/1.1):語意與內容", RFC 7231, DOI 10.17487/RFC7231, 2014 年 6 月。
[W3C.WD-fragid-best-practices-20121025] Tennison, J., "片段識別符與媒體類型定義的最佳實務", World Wide Web Consortium LastCall WD-fragid-best-practices-20121025, 2012 年 10 月。
[json-schema-validation] Wright, A.G. Luff, "JSON 結構描述驗證:JSON 結構驗證的詞彙", Internet-Draft draft-wright-json-schema-validation-00, 2016 年 10 月。
[json-hyper-schema] Wright, A.G. Luff, "JSON 超結構描述:用於 JSON 超媒體註釋的詞彙", Internet-Draft draft-wright-json-schema-hyperschema-00, 2016 年 10 月。

附錄 A. 鳴謝

感謝 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 對文件所做的提交和修正。

附錄 B. 變更記錄

[CREF3]此章節將在離開網際網路草案狀態前移除。

draft-wright-json-schema-01

draft-wright-json-schema-00

draft-zyp-json-schema-04

draft-zyp-json-schema-00

作者地址

Austin Wright (編輯) 電子郵件:[email protected]
Henry Andrews (編輯) Cloudflare, Inc. 電子郵件:[email protected]