網際網路草案 | 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.dev.org.tw/。¶
如需提供回饋意見,請使用此問題追蹤器、首頁上列出的溝通方式或電子郵件給文件編輯者。¶
此網際網路草案的提交完全符合 BCP 78 和 BCP 79 的規定。¶
網際網路草案是網際網路工程任務組 (IETF) 的工作文件。請注意,其他組也可能將工作文件作為網際網路草案發布。目前的網際網路草案清單位於 https://datatracker.ietf.org/drafts/current/。¶
網際網路草案是有效期最長為六個月的草擬文件,隨時可能被其他文件更新、取代或廢止。將網際網路草案用作參考資料或將其引用為「正在進行中的工作」以外的情況是不適當的。¶
此網際網路草案將於 2022 年 12 月 18 日到期。¶
著作權 (c) 2022 IETF Trust 和被認定為文件作者的人士。保留所有權利。¶
本文件受 BCP 78 和 IETF Trust 關於 IETF 文件的法律條款約束 (https://trustee.ietf.org/license-info),這些條款在本文件發布之日生效。請仔細審閱這些文件,因為它們描述您關於本文件的權利和限制。從本文件中提取的程式碼元件必須包含修訂的 BSD 許可文字,如 Trust 法律條款第 4.e 節所述,並按修訂的 BSD 許可證中的描述提供,不提供擔保。¶
JSON 綱要是一種用於定義 JSON 資料結構的 JSON 媒體類型。JSON 綱要旨在定義 JSON 資料的驗證、文件、超連結導覽和互動控制。¶
本規範定義了 JSON 綱要的核心術語和機制,包括透過參照指向另一個 JSON 綱要、解參照 JSON 綱要參照、指定正在使用的方言、指定方言的詞彙表需求,以及定義預期的輸出。¶
其他規範定義了執行有關驗證、連結、註解、導覽和互動的斷言的詞彙表。¶
本文檔中的關鍵字「必須(MUST)」、「不得(MUST NOT)」、「必要(REQUIRED)」、「應當(SHALL)」、「不應當(SHALL NOT)」、「應該(SHOULD)」、「不應該(SHOULD NOT)」、「建議(RECOMMENDED)」、「可以(MAY)」和「可選(OPTIONAL)」應按 RFC 2119 [RFC2119] 中所述進行解釋。¶
本文檔中的術語「JSON」、「JSON 文本」、「JSON 值」、「成員」、「元素」、「物件」、「陣列」、「數字」、「字串」、「布林值」、「真」、「假」和「空值」應按 RFC 8259 [RFC8259] 中定義進行解釋。¶
本文檔提出了一種新的媒體類型「application/schema+json」,用於識別描述 JSON 資料的 JSON 綱要。它還提出了一個額外的可選媒體類型「application/schema-instance+json」,以提供額外的整合功能。JSON 綱要本身就是 JSON 文件。本規範以及相關規範定義了一些關鍵字,允許作者以多種方式描述 JSON 資料。¶
JSON 綱要使用關鍵字來對 JSON 實例斷言約束,或使用額外資訊註解這些實例。額外的關鍵字用於對更複雜的 JSON 資料結構應用斷言和註解,或基於某種條件。¶
為了便於重複使用,關鍵字可以組織成詞彙表。詞彙表由關鍵字列表及其語法和語義組成。方言定義為一組詞彙表及其在元綱要中識別的必要支援。¶
JSON 綱表可以透過定義額外的詞彙表來擴展,或者可以透過在任何詞彙表之外定義額外的關鍵字來以較不正式的方式擴展。無法識別的個別關鍵字只會將其值收集為註解,而當宣告正在使用哪些詞彙表時,可以控制對無法識別的詞彙表的行為。¶
本文檔定義了一個核心詞彙表,任何實作都必須支援,且無法停用。其關鍵字都以 "$" 字元作為前綴,以強調其必要性。此詞彙表對於「application/schema+json」媒體類型的運作至關重要,並用於引導其他詞彙表的載入。¶
此外,本文檔還定義了一個建議的關鍵字詞彙表,用於有條件地應用子綱要,以及將子綱要應用於物件和陣列的內容。無論這些綱要的目的是用於斷言驗證、註解或兩者,都需要此詞彙表或非常相似的詞彙表來編寫非簡單 JSON 實例的綱要。雖然它不是必要的核心詞彙表的一部分,但為了最大的互通性,此額外詞彙表包含在本文檔中,並強烈建議使用。¶
用於結構驗證或超媒體註解等目的的進一步詞彙表在其他文件中定義。這些其他文件分別定義了一種方言,該方言收集了為該文件目的編寫綱要所需的標準詞彙表集。¶
JSON 文件是由 application/json 媒體類型描述的資訊資源(一連串的八位元組)。¶
在 JSON 綱要中,由於其定義的資料模型,「JSON 文件」、「JSON 文本」和「JSON 值」等術語可以互換使用。¶
JSON 綱表僅針對 JSON 文件定義。但是,任何可以根據 JSON 綱要資料模型解析或處理的文件或記憶體結構都可以針對 JSON 綱要進行解釋,包括諸如 CBOR [RFC7049] 等媒體類型。¶
應用綱要的 JSON 文件稱為「實例」。¶
JSON 綱要針對「application/json」或相容文件進行定義,包括帶有「+json」結構語法尾碼的媒體類型。¶
其中,本規範定義了「application/schema-instance+json」媒體類型,該媒體類型定義了 URI 中片段的處理。¶
JSON 綱要根據資料模型解釋文件。根據此資料模型解釋的 JSON 值稱為「實例」。¶
實例具有六種基本類型之一,並且根據類型具有一系列可能的值:¶
因此,包括資料模型中相等的數字的不同詞彙表示在內的空白和格式設定問題,都不在 JSON 綱要的範圍內。希望使用此類詞彙表示差異的 JSON 綱要 詞彙表 (第 8.1 節) 應定義關鍵字,以便在資料模型中精確地解釋格式化字串,而不是依賴於可用的原始 JSON 表示 Unicode 字元。¶
由於物件不能有兩個具有相同鍵的屬性,因此嘗試在單一物件中定義兩個具有相同鍵的屬性的 JSON 文件的行為是未定義的。¶
請注意,JSON 綱要詞彙表可以自由定義自己的擴展類型系統。這不應與此處定義的核心資料模型類型混淆。例如,「integer」是詞彙表將其定義為關鍵字值的合理類型,但是資料模型不會區分整數和其他數字。¶
當且僅當兩個 JSON 實例的類型相同,並且根據資料模型具有相同的值時,才認為它們相等。具體來說,這表示:¶
此定義隱含著陣列的長度必須相同,物件必須具有相同數量的成員,物件中的屬性是無序的,沒有辦法定義具有相同鍵的多個屬性,而且僅格式設定差異(縮排、逗號的位置、尾隨零)是無關緊要的。¶
可以將 JSON 綱要與 JSON 綱要資料模型的超集一起使用,其中實例可能位於六個 JSON 資料類型之外。¶
在這種情況下,註解仍然適用;但是大多數驗證關鍵字將沒有用處,因為它們將始終通過或始終失敗。¶
自訂詞彙表可以定義對核心資料模型超集的支援。綱要本身可能只能在此超集中表達;例如,為了使用「const」關鍵字。¶
JSON Schema 文件,或簡稱 schema,是一種用於描述實例的 JSON 文件。 schema 本身可以被解釋為一個實例,但應該始終給予 "application/schema+json" 媒體類型,而不是 "application/schema-instance+json"。 "application/schema+json" 媒體類型被定義為提供 "application/schema-instance+json" 所提供的片段識別符語法和語義的超集。¶
JSON Schema 必須是一個物件或一個布林值。¶
應用於實例的物件屬性稱為關鍵字,或 schema 關鍵字。廣泛來說,關鍵字可分為五類:¶
關鍵字可能屬於多個類別,儘管應用器應僅根據其子 schema 的結果產生斷言結果。它們不應定義獨立於其子 schema 的額外約束。¶
在同一個 schema 物件內的屬性關鍵字稱為相鄰關鍵字。¶
擴充關鍵字,即在此文件及其相關文件中定義的關鍵字之外的關鍵字,可以自由定義其他行為。¶
JSON Schema 可能包含非 schema 關鍵字的屬性。未知關鍵字應被視為註解,其中關鍵字的值是註解的值。¶
一個空 schema 是一個沒有屬性或只有未知屬性的 JSON Schema。¶
布林值 schema 值 "true" 和 "false" 是微不足道的 schema,無論實例值如何,它們總是產生自身作為斷言結果。它們永遠不會產生註解結果。¶
這些布林值 schema 的存在是為了闡明 schema 作者的意圖並促進 schema 處理的優化。它們的行為與以下 schema 物件相同(其中 "not" 是本文定義的子 schema 應用詞彙的一部分)。¶
雖然空 schema 物件是明確的,但 "false" schema 有許多可能的等效項。使用布林值可確保人類讀者和實作都能清楚了解其意圖。¶
schema 詞彙表,或簡稱詞彙表,是一組關鍵字、它們的語法和語義。詞彙表通常圍繞特定目的組織。JSON Schema 的不同用途,例如驗證、超媒體或使用者介面產生,將涉及不同的詞彙表集合。¶
詞彙表是 JSON Schema 中重用的主要單元,因為 schema 作者可以指示處理 schema 所需或可選的詞彙表。由於詞彙表由元 schema 中的 URI 識別,因此通用實作可以載入擴充來支援先前未知的詞彙表。雖然可以在任何詞彙表之外支援關鍵字,但沒有類似的機制來指示單個關鍵字的使用。¶
schema 詞彙表可以由從非正式描述到標準提案的任何內容定義,具體取決於受眾和互操作性期望。特別是,為了促進非公開組織內詞彙表的使用,詞彙表規範無需在其使用範圍之外發布。¶
本身描述 schema 的 schema 稱為元 schema。元 schema 用於驗證 JSON Schema 並指定它們正在使用的詞彙表。¶
通常,元 schema 將指定一組詞彙表,並驗證符合這些詞彙表語法的 schema。但是,元 schema 和詞彙表是分開的,以便允許元 schema 比詞彙表規範要求更嚴格或更寬鬆地驗證 schema 一致性。元 schema 也可能描述和驗證不屬於正式詞彙表的其他關鍵字。¶
JSON Schema 資源是一個 schema,它由 標準 [RFC6596] 使用 絕對 URI [RFC3986] 識別。如果產生的輔助資源(如 RFC 3986 的 3.5 節 [RFC3986] 中定義)與主要資源相同,則 schema 資源也可能由 URI 識別,包括帶有片段的 URI。當使用空片段或將一個 schema 資源嵌入另一個時,可能會發生這種情況。任何帶有片段的此類 URI 都被視為非標準的。¶
根 schema 是包含所討論的整個 JSON 文件的 schema。根 schema 始終是一個 schema 資源,其中 URI 的確定方式如 9.1.1 節所述。 請注意,以另一種格式嵌入 schema 的文件將不會在這個意義上具有根 schema 資源。此類用法如何與 JSON Schema 文件和資源概念相符將在未來的草案中闡明。 ¶
某些關鍵字本身採用 schema,允許巢狀 JSON Schema:¶
{ "title": "root", "items": { "title": "array item" } }¶
在此範例文件中,標題為「array item」的 schema 是子 schema,而標題為「root」的 schema 是根 schema。¶
與根 schema 一樣,子 schema 要么是一個物件,要么是一個布林值。¶
如 8.2.1 節所述,JSON Schema 文件可以包含多個 JSON Schema 資源。在沒有限定詞的情況下使用時,「根 schema」一詞是指文件的根 schema。在某些情況下,會討論資源根 schema。資源的根 schema 是其頂層 schema 物件,如果將資源提取到獨立的 JSON Schema 文件中,它也將是文件根 schema。¶
無論多個 schema 資源是嵌入還是使用參考連結,它們的處理方式相同,具有相同的可用行為。¶
根據 RFC 6839 [RFC6839] 的 3.1 節,為任何 +json 媒體類型指定的片段識別符語法和語義應與為「application/json」指定的相同。(在本文件發布時,沒有為「application/json」定義片段識別語法。)¶
此外,「application/schema+json」媒體類型支援兩種片段識別符結構:純名稱和 JSON 指標。「application/schema-instance+json」媒體類型支援一種片段識別符結構:JSON 指標。¶
在 RFC 6901 [RFC6901] 中描述了使用 JSON 指標作為 URI 片段識別符。對於支援兩種片段識別符語法的「application/schema+json」,與 JSON 指標語法匹配的片段識別符,包括空字串,必須解釋為 JSON 指標片段識別符。¶
根據 W3C 的 片段識別符最佳實務 [W3C.WD-fragid-best-practices-20121025],「application/schema+json」中的純名稱片段識別符保留用於參考本地命名的 schema。所有與 JSON 指標語法不匹配的片段識別符都必須解釋為純名稱片段識別符。¶
在 「$anchor」關鍵字(第 8.2.2 節) 節中指定了在「application/schema+json」文件中定義和參考純名稱片段識別符。¶
實例可以是 JSON [RFC8259] 定義的任何有效 JSON 值。JSON Schema 對類型沒有任何限制:JSON Schema 可以描述任何 JSON 值,包括例如 null。¶
JSON Schema 與程式語言無關,並支援資料模型中描述的完整數值範圍。然而,請注意,某些語言和 JSON 解析器可能無法在記憶體中表示 JSON 可描述的完整數值範圍。¶
關鍵字「可以」使用正規表示式來表達約束,或將實例值限制為正規表示式。這些正規表示式「應該」根據 ECMA-262,第 21.2.1 節 [ecma262] 中描述的正規表示式方言有效。¶
正規表示式「應該」使用 "u" 旗標(或等效項)構建,以提供 Unicode 支援,或以提供 ECMA-262 定義的 Unicode 支援的方式進行處理。¶
此外,鑑於正規表示式結構支援的高度差異,schema 作者「應該」將自己限制在以下正規表示式符號:¶
最後,實作「不能」將正規表示式視為錨定的,無論是在開頭還是在結尾。這表示,例如,模式 "es" 符合 "expression"。 ¶
任何實體「可以」定義其他 schema 關鍵字和 schema 詞彙表。除非有明確的協議,否則 schema 作者「不應」期望不直接說明此類支援的實作支援這些額外的關鍵字和詞彙表。實作「應該」將它們不支援的關鍵字視為註解,其中關鍵字的值為註解的值。¶
實作「可以」提供註冊或載入它們不直接支援的詞彙表處理常式的功能。註冊和實作此類處理常式的確切機制是取決於實作的。¶
JSON Schema 關鍵字分為幾個通用行為類別。斷言驗證實例是否滿足約束,產生布林結果。註解附加應用程式可能以其認為合適的任何方式使用的資訊。應用程式將子schema應用於實例的部分並組合其結果。¶
擴展關鍵字「應該」保留在這些類別中,請記住,特別是註解非常靈活。複雜行為通常最好根據註解資料委託給應用程式,而不是直接作為 schema 關鍵字實作。但是,擴展關鍵字「可以」為特殊目的定義其他行為。¶
針對 schema 評估實例涉及針對實例內適當的位置處理 schema 中的所有關鍵字。通常,會處理應用程式關鍵字,直到達到沒有應用程式(因此沒有子schema)的 schema 物件。實例中適當的位置會根據 schema 物件中的斷言和註解關鍵字進行評估,並且它們的結果會根據應用程式的規則收集到父 schema 中。¶
一旦所有子schema都經過評估,父 schema 物件的評估就可以完成,儘管在某些情況下,由於斷言結果,評估可能會被短路。收集註解時,由於需要檢查所有子schema以收集註解,包括那些無法進一步更改斷言結果的子schema,因此無法進行某些斷言結果短路。¶
雖然大多數 JSON Schema 關鍵字可以自行評估,或最多只需要考慮同一 schema 物件中相鄰關鍵字的值或結果,但少數關鍵字具有更複雜的行為。¶
關鍵字的詞彙範圍由物件和陣列的巢狀 JSON 資料結構決定。最大的範圍是整個 schema 文件。最小範圍是沒有子schema的單個 schema 物件。¶
關鍵字「可以」使用部分值進行定義,例如 URI 參考,必須針對另一個值(例如另一個 URI 參考或完整的 URI)解析該值,該值是透過 JSON 文件的詞彙結構找到的。"$id"、"$ref" 和 "$dynamicRef" 核心關鍵字,以及 "base" JSON Hyper-Schema 關鍵字,是此類行為的範例。¶
請注意,某些關鍵字(例如 "$schema")適用於整個 schema 資源的詞彙範圍,因此「必須」僅出現在 schema 資源的根 schema 中。¶
其他關鍵字可以考慮在 schema 評估期間存在的動態範圍,通常與實例文件一起。最外層的動態範圍是開始處理的 schema 物件,即使它不是 schema 資源根。從此根 schema 到任何特定關鍵字的路徑(包括任何可能已解析的 "$ref" 和 "$dynamicRef" 關鍵字)被視為關鍵字的「驗證路徑」。¶
詞彙和動態範圍會對齊,直到遇到參考關鍵字。雖然跟隨參考關鍵字會將處理從一個詞彙範圍移動到另一個詞彙範圍,但從動態範圍的角度來看,跟隨參考與下降到作為值存在的子schema沒有區別。該參考的遠端上的關鍵字透過動態範圍解析資訊時,會將參考的原始端視為其動態父級,而不是檢查本地詞彙封閉父級。¶
動態範圍的概念主要與 "$dynamicRef" 和 "$dynamicAnchor" 一起使用,並且應被視為進階功能,並且在定義其他關鍵字時應謹慎使用。它也會在報告錯誤和收集的註解中出現,因為可以使用不同的動態範圍重複訪問相同的詞彙範圍。在這種情況下,務必告知使用者產生錯誤或註解的動態路徑。¶
關鍵字行為「可以」根據 子schema (第 4.3.5 節) 和/或相鄰關鍵字(同一 schema 物件內的關鍵字)及其子schema的註解結果定義。此類關鍵字「不能」導致循環依賴。關鍵字「可以」根據同一 schema 物件 (第 4.3 節) 中是否存在其他關鍵字來修改其行為。¶
遺失的關鍵字「不能」產生錯誤的斷言結果,「不能」產生註解結果,並且「不能」導致任何其他 schema 作為其自身行為定義的一部分進行評估。但是,鑑於遺失的關鍵字不提供註解,缺少註解結果可能會間接更改其他關鍵字的行為。¶
在某些情況下,關鍵字的遺失關鍵字斷言行為與特定值產生的行為相同,並且關鍵字定義「應該」在已知的情況下註明此類值。但是,即使產生預設行為的值在存在時會產生註解結果,預設行為仍然「不能」產生註解。¶
由於註解收集在計算和記憶體方面都會增加顯著的成本,因此實作「可以」選擇不使用此功能。根據收集的註解指定的關鍵字「應該」在適當時描述合理的替代方法。本文檔中的 "items" 和 "additionalProperties" 關鍵字說明了此方法。¶
請注意,當關鍵字無法使用此類替代方法時,不支援註解收集的實作將無法支援那些關鍵字或包含這些關鍵字的詞彙表。¶
識別碼定義 schema 的 URI,或影響此類 URI 在 參考 (第 8.2.3 節) 中的解析方式,或兩者兼具。本文檔中定義的「核心」詞彙定義了幾個識別關鍵字,最值得注意的是 "$id"。 ¶
標準 schema URI 在處理實例時「不能」變更,但影響 URI 參考解析的關鍵字「可以」具有僅在執行階段完全確定的行為。¶
雖然可以自訂識別碼關鍵字,但詞彙設計者應注意不要干擾核心關鍵字的功能。例如,此規範中的 "$dynamicAnchor" 關鍵字將其 URI 解析效果限制為匹配的 "$dynamicRef" 關鍵字,而不會干擾 "$ref" 的行為。¶
應用器允許建構比單一 schema 物件更複雜的 schema。針對一個實例評估 schema 文件(第 4.3 節)的過程,會先將 根 schema(第 4.3.5 節)應用於完整的實例文件。接著,使用稱為應用器的關鍵字來決定要套用哪些額外的 schema。這些 schema 可以就地應用於目前的位置,或是應用於子位置。¶
要套用的 schema 可能以子 schema 的形式存在,構成關鍵字值的部分或全部。或者,應用器可以參照同一 schema 文件中或其他 schema 文件中的 schema。識別這類參照 schema 的機制由關鍵字定義。¶
應用器關鍵字也定義了子 schema 或參照 schema 的布林值 斷言(第 7.6 節)結果如何被修改和/或組合,以產生應用器的布林值結果。應用器可以將任何布林邏輯運算應用於子 schema 的斷言結果,但絕不能引入新的斷言條件。¶
註解(第 7.7 節)結果會與實例位置和 schema 關鍵字的位置一起保留,以便應用程式可以決定如何解釋多個值。¶
如第 7.5 節所述,應用器關鍵字可以參照要套用的 schema,而不是將其作為應用器值中的子 schema 包含。在這種情況下,正在套用的 schema 被稱為「參照的 schema」,而包含應用器關鍵字的 schema 則為「參照 schema 的 schema」。¶
根 schema 和子 schema 是基於 schema 在 schema 文件中的位置的靜態概念,而參照的 schema 和參照 schema 的 schema 則是動態的。在針對 schema 評估實例的過程中,不同的 schema 對可能會發現自己處於不同的參照和參照 schema 的安排中。¶
對於某些透過參照的應用器(例如 "$ref"(第 8.2.3.1 節)),可以透過對 schema 文件的詞彙範圍進行靜態分析來確定參照的 schema。其他應用器,例如 "$dynamicRef"(搭配 "$dynamicAnchor"),可能使用動態作用域,因此只能在評估具有實例的 schema 的過程中解析。¶
JSON Schema 可用於斷言 JSON 文件上的約束,該約束會通過或未通過斷言。這種方法可用於驗證是否符合約束,或記錄滿足約束所需的要求。¶
JSON Schema 實作在針對 schema 斷言評估實例時會產生單一布林值結果。¶
實例只能未通過 schema 中存在的斷言。¶
大多數斷言僅約束特定基本類型中的值。當實例的類型不是關鍵字所針對的類型時,則認為該實例符合斷言。¶
例如,來自配套的 驗證詞彙 [json-schema-validation] 的 "maxLength" 關鍵字:只會限制某些字串(過長)為無效。如果實例是數字、布林值、null、陣列或物件,則它對於此斷言而言是有效的。¶
這種行為允許關鍵字更輕鬆地與可以具有多個基本類型的實例一起使用。配套的驗證詞彙也包含一個 "type" 關鍵字,它可以獨立地將實例限制為一個或多個基本類型。這允許簡潔地表達使用案例,例如可能傳回特定長度的字串或 null 值的函式:¶
{ "type": ["string", "null"], "maxLength": 255 }¶
如果 "maxLength" 也將實例類型限制為字串,則表達會變得更加繁瑣,因為如編寫的範例實際上不允許 null 值。除非另有明確規定,否則會單獨評估每個關鍵字,因此如果 "maxLength" 將實例限制為字串,則在 "type" 中包含 "null" 將不會有任何有用的效果。¶
每當實例針對包含註解的 schema 物件及其所有父 schema 物件進行驗證時,JSON Schema 都可以使用資訊來註解實例。該資訊可以是簡單的值,也可以根據實例內容計算得出。¶
註解會附加到實例中的特定位置。由於許多子 schema 可以應用於任何單一位置,因此應用程式可能需要決定如何處理由不同 schema 物件中相同 schema 關鍵字附加到相同實例位置的不同註解值。¶
與斷言結果不同,註解資料可以採用多種形式,這些形式會提供給應用程式以供它們自行使用。JSON Schema 實作預期不會代表應用程式使用收集到的資訊。¶
除非另有規定,否則註解關鍵字的值為關鍵字的值。但是,其他行為是可能的。例如,JSON Hyper-Schema [json-hyper-schema] 的 "links" 關鍵字是一個複雜的註解,會產生部分基於實例資料的值。¶
雖然斷言可以使用「短路」評估,但收集註解需要檢查應用於實例位置的所有 schema,即使它們無法更改整體斷言結果。唯一的例外是,如果 schema 物件的驗證失敗,則可以略過該 schema 物件的子 schema,因為不會為失敗的 schema 保留註解。¶
註解由明確定義註解收集行為的關鍵字收集。請注意,布林 schema 無法產生註解,因為它們不使用關鍵字。¶
收集的註解必須包含以下資訊:¶
應用程式可以根據提供值的 schema 位置來決定要使用多個註解值中的哪一個。這是為了實現彈性的使用。收集 schema 位置有助於這種使用方式。¶
例如,請考慮以下 schema,它使用來自 驗證規格 [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 } } }¶
在此範例中,功能 A 和功能 B 都使用了可重複使用的 "enabledToggle" schema。該 schema 使用 "title"、"description" 和 "default" 註解。因此,應用程式必須決定如何處理功能 A 的額外 "default" 值和功能 B 的額外 "description" 值。¶
應用程式程式設計師和 schema 作者需要就使用方式達成一致。在此範例中,我們假設他們同意使用最明確的 "default" 值,並且會靜默忽略任何其他更通用的 "default" 值。我們也假設他們同意使用所有 "description" 文字,從最通用的文字開始,到最明確的文字結束。這要求 schema 作者編寫以這種方式組合時有效的描述。¶
應用程式可以使用 schema 位置路徑來確定哪些值是什麼。功能立即 "enabled" 屬性 schema 中的值更具體,而使用 "$ref" 參照的可重複使用 schema 下的值則更通用。schema 位置路徑會顯示是否透過交叉 "$ref" 找到每個值。¶
因此,功能 A 將使用預設值 true,而功能 B 將使用通用的預設值 null。功能 A 將只有來自 "enabledToggle" schema 的通用描述,而功能 B 將使用該描述,並附加其本地定義的描述,說明如何解釋 null 值。¶
請注意,不同的應用程式可能會採用其他合理的方法。例如,應用程式可能會認為存在兩個不同的 "default" 值是一個錯誤,而不管它們的 schema 位置如何。¶
產生 false 斷言結果的 Schema 物件絕不能產生任何註解結果,無論是來自它們自己的關鍵字還是來自子 schema 中的關鍵字。¶
請注意,整體 schema 結果可能仍然包含從其他 schema 位置收集的註解。考慮到此 schema:¶
{ "oneOf": [ { "title": "Integer Value", "type": "integer" }, { "title": "String Value", "type": "string" } ] }¶
針對實例 "This is a string"
,會捨棄標題註解「整數值」,因為該 schema 物件中的類型斷言失敗。「字串值」標題註解會保留,因為該實例通過字串類型斷言。¶
除了可能定義它們自己的註解結果外,應用器關鍵字還會聚合它們的子 schema 或參照 schema 中收集的註解。¶
第四類關鍵字僅保留一個位置,以容納 schema 作者感興趣的、不適合重複使用的可重複使用元件或資料。這些關鍵字不影響驗證或註解結果。它們在核心詞彙中的目的是確保某些目的可以使用這些位置,並且不會被擴充關鍵字重新定義。¶
雖然這些關鍵字不會直接影響結果,但如9.4.2節所述,未辨識的擴充關鍵字會保留可重複使用 schema 的位置,在某些情況下可能會對參照產生不良的交互作用。¶
雖然定義為本文件或相關文件一部分的詞彙都未定義可以定位和/或載入實例資料的關鍵字,但其他詞彙可能希望這樣做。¶
關鍵字可以被定義為使用 JSON 指標 (JSON Pointers) 或相對 JSON 指標 (Relative JSON Pointers) 來檢查目前評估位置之外的實例部分。¶
允許使用相對 JSON 指標調整位置的關鍵字,如果需要預設值,則應預設使用目前位置。¶
本節中宣告的關鍵字(皆以 "$" 開頭)構成 JSON Schema 核心詞彙。這些關鍵字是處理任何綱要 (schema) 或元綱要 (meta-schema) (包括跨多個文件分割的綱要或元綱要)所必需的,或是為了保留關鍵字以用於需要保證互通性的目的而存在。¶
為了引導進一步詞彙的處理,必須始終將核心詞彙視為強制性的。使用 "$vocabulary" (第 8.1 節) 關鍵字宣告所使用詞彙的元綱要,必須明確列出核心詞彙,其值必須為 true,表示為必要詞彙。¶
此詞彙(且僅限於此詞彙)的 false 值行為是未定義的,當存在 "$vocabulary" 但未包含核心詞彙時的行為也是未定義的。但是,建議實作方式偵測這些情況,並在發生時引發錯誤。宣告元綱要可選地使用核心詞彙是沒有意義的。¶
不使用 "$vocabulary" 的元綱要必須被視為需要核心詞彙,如同其 URI 以 true 值存在一樣。¶
核心詞彙目前的 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/core>。¶
對應的元綱要目前的 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/core。¶
雖然 "$" 前綴並未正式保留給核心詞彙使用,但建議擴充關鍵字(在詞彙或其他方面)以 "$" 以外的字元開頭,以避免未來可能發生的衝突。¶
元綱要和詞彙這兩個概念用於告知實作方式如何解讀綱要。每個綱要都有一個元綱要,可以使用 "$schema" 關鍵字宣告。¶
元綱要有兩個用途:¶
元綱要與詞彙是分開的,以允許以不同方式組合詞彙,並讓元綱要作者施加額外的限制,例如禁止某些關鍵字,或執行異常嚴格的語法驗證,這可能在開發和測試週期中完成。每個詞彙通常會識別僅包含詞彙關鍵字的元綱要。¶
元綱要撰寫是 JSON Schema 的進階用法,因此元綱要功能的設計強調彈性而非簡潔。¶
"$schema" 關鍵字既用作 JSON Schema 方言識別符號,也用作資源的識別符號,該資源本身是 JSON Schema,它描述了為此特定方言編寫的有效綱要集。¶
此關鍵字的值必須是 URI [RFC3986](包含 scheme),且此 URI 必須正規化。目前的綱要必須根據此 URI 識別的元綱要進行驗證。¶
如果此 URI 識別可檢索的資源,則該資源的媒體類型應為 "application/schema+json"。 ¶
"$schema" 關鍵字應在文件根綱要物件中使用,並且可以在嵌入式綱要資源的根綱要物件中使用。它不得出現在非資源根綱要物件中。如果文件根綱要中缺少此關鍵字,則產生的行為由實作方式定義。¶
此屬性的值定義於本文件和其他文件中,以及由其他方定義。¶
"$vocabulary" 關鍵字用於元綱要中,以識別可供使用該元綱要描述之綱要使用的詞彙。它也用於指示每個詞彙是必要還是可選的,因為實作方式必須理解必要的詞彙才能成功處理綱要。這些資訊共同構成一種方言。任何實作方式所理解的詞彙都必須以符合該詞彙內語義定義的方式進行處理。¶
此關鍵字的值必須是一個物件。物件中的屬性名稱必須是 URI(包含 scheme),且此 URI 必須正規化。每個作為屬性名稱出現的 URI 都會識別一組特定的關鍵字及其語義。¶
URI 可以是 URL,但可檢索資源的性質目前未定義,並保留供將來使用。詞彙作者可以使用詞彙規格的 URL(以人類可讀的媒體類型,例如 text/html 或 text/plain)作為詞彙 URI。 詞彙文件可能會在即將發布的草案中加入。目前,識別關鍵字集被認為是足夠的,因為它與元綱要驗證一起是目前「詞彙」運作的方式。任何未來詞彙文件格式都將指定為 JSON 文件,因此同時使用 text/html 或其他非 JSON 格式不會產生任何未來不明確之處。¶
物件屬性的值必須是布林值。如果值為 true,則無法識別該詞彙的實作方式必須拒絕處理任何使用 "$schema" 宣告此元綱要的綱要。如果值為 false,則無法識別該詞彙的實作方式應繼續處理此類綱要。如果實作方式理解該詞彙,則該值沒有影響。¶
根據6.5,無法識別的關鍵字應被視為註解。對於無法識別詞彙定義的關鍵字,情況仍然如此。目前無法區分在詞彙中定義的無法識別關鍵字和不屬於任何詞彙的關鍵字。¶
"$vocabulary" 關鍵字應在任何用作元綱要的綱要文件的根綱要中使用。它不得出現在子綱要中。¶
在未作為元綱要處理的綱要文件中,必須忽略 "$vocabulary" 關鍵字。這允許針對其自身的元綱要 M' 驗證元綱要 M,而無需驗證器理解 M 所宣告的詞彙。¶
如果缺少 "$vocabulary",則實作方式可以根據元綱要來確定行為,如果可以從參考綱要的 "$schema" 關鍵字的 URI 值中識別該元綱要。這是在詞彙存在之前識別行為(例如 Hyper-Schema 使用)的方式。¶
如果綱要參考的元綱要無法識別或遺失,則行為由實作方式定義。如果實作方式繼續處理綱要,則必須假設使用核心詞彙。如果實作方式是針對特定目的而建構的,則應假設使用所有與該目的最相關的詞彙。¶
例如,驗證器實作方式應假設使用本規範和配套的驗證規範中的所有詞彙。¶
請注意,"$vocabulary" 的處理限制意味著使用 "$ref" 或類似關鍵字參考其他元綱要的元綱要不會自動繼承其他元綱要的詞彙宣告。所有此類宣告都必須在每個用作元綱要的綱要文件的根目錄中重複。這在範例元綱要(附錄 D.2)中說明。 此要求允許實作方式在每個元綱要的單一位置中找到所有詞彙需求資訊。由於綱要可擴充性意味著可以透過參考來組合更精細的元綱要的方式是無窮無盡的,因此要求實作方式預期所有可能性並在參考的元綱要中搜尋詞彙將會過於繁瑣。¶
為了修正錯誤,可能會在規格草案之間發布更新的詞彙和元綱要 URI。實作方式應考慮在本規範草案之後和下一個規範草案之前的 URI,以指示與此處列出的語法和語義相同。¶
為了區分龐大生態系統中的綱要,綱要是透過 URI [RFC3986] 來識別的,並且可以透過指定其 URI 來嵌入對其他綱要的參考。¶
一些關鍵字可以接受相對 URI 參考 [RFC3986],或用於建構相對 URI 參考的值。對於這些關鍵字,必須建立基礎 URI 才能解析參考。¶
"$id" 關鍵字使用其 標準 [RFC6596] URI 來識別綱要資源。¶
請注意,此 URI 是一個識別符號,不一定是網路定位器。在網路可定址 URL 的情況下,綱要不需要從其標準 URI 下載。¶
如果存在,此關鍵字的值必須是字串,且必須表示有效的 URI 參考 [RFC3986]。此 URI 參考應正規化,且必須解析為 絕對 URI [RFC3986](不帶片段),或解析為具有空片段的 URI。¶
不建議使用空的片段形式,保留它僅是為了向後相容,並且因為 application/schema+json 媒體類型定義了帶有空片段的 URI 與移除片段的相同 URI 指向相同的資源。然而,由於這種等效性並非 RFC 3986 正規化流程 [RFC3986] 的一部分,實作者和 schema 作者不能依賴通用的 URI 函式庫來理解它。¶
因此,"$id" 必須不包含非空的片段,而且應該不包含空的片段。絕對 URI 形式必須被視為標準 URI,無論是否存在空的片段。目前允許空的片段是因為較舊的中繼 schema 在它們的 $id(或之前的 id)中有一個空的片段。未來的草案可能會直接禁止在 "$id" 中使用任何片段,甚至包括空的片段。¶
根據 RFC 3986 第 5.1.1 節 [RFC3986] 關於內容中嵌入的基礎 URI,絕對 URI 也作為 schema 資源內關鍵字中相對 URI 參考的基礎 URI。¶
子 schema 中存在 "$id" 表示該子 schema 在單一 schema 文件內構成一個不同的 schema 資源。此外,根據 RFC 3986 第 5.1.2 節 [RFC3986] 關於封裝實體,如果子 schema 中的 "$id" 是一個相對 URI 參考,則解析該參考的基礎 URI 是父 schema 資源的 URI。¶
如果沒有父 schema 物件明確地使用 "$id" 將其自身識別為資源,則基礎 URI 是整個文件的 URI,如前一節 (第 9.1.1 節) 中給出的步驟所建立的。¶
JSON Schema 文件的根 schema 應該包含一個 "$id" 關鍵字,其中包含一個絕對 URI [RFC3986](包含 scheme,但不包含片段)。¶
使用 JSON Pointer 片段需要了解 schema 的結構。當編寫旨在提供可重複使用的 schema 文件時,最好使用未綁定到任何特定結構位置的純名稱片段。這允許重新定位子 schema,而無需更新 JSON Pointer 參考。¶
"$anchor" 和 "$dynamicAnchor" 關鍵字用於指定此類片段。它們是識別符關鍵字,只能用於創建純名稱片段,而不是像 "$id" 那樣創建絕對 URI。¶
附加結果片段的基礎 URI 是包含相關 "$anchor" 或 "$dynamicAnchor" 的 schema 資源的標準 URI。如上一節所述,這可以是相同或父 schema 物件中最接近的 "$id",也可以是根據 RFC 3986 確定的文件的基礎 URI。¶
與 URI 的通常用法不同,"$dynamicAnchor" 表示當與 "$dynamicRef" 關鍵字一起使用時,該片段是一個擴展點。這個底層的進階功能使得擴展遞迴 schema(例如中繼 schema)更容易,而不會對該擴展施加任何特定的語義。有關詳細資訊,請參閱 "$dynamicRef" (第 8.2.3.2 節) 的章節。¶
在大多數情況下,正常的片段行為既足夠又更直觀。因此,建議使用 "$anchor" 來建立純名稱片段,除非有明確需要使用 "$dynamicAnchor"。¶
如果存在此關鍵字,則其值必須是一個字串,並且必須以字母 ([A-Za-z]) 或底線 ("_") 開頭,後跟任意數量的字母、數字 ([0-9])、連字號 ("-")、底線 ("_") 和句點 (".")。這符合 XML 的 NCName 產生式 [xml-names] 的 US-ASCII 部分。請注意,錨點字串不包含 "#" 字元,因為它不是 URI 參考。當在 URI 中使用時,"$anchor": "foo" 會變成片段 "#foo"。請參閱下方的完整範例。¶
在同一個資源內,使用 "$anchor" 和/或 "$dynamicAnchor" 的任何組合多次指定相同的片段名稱的效果是未定義的。如果檢測到此類使用情況,實作可能會引發錯誤。¶
可以使用幾個關鍵字來參考要應用於目前實例位置的 schema。"$ref" 和 "$dynamicRef" 是應用關鍵字,將參考的 schema 應用於實例。¶
由於 "$ref" 和 "$dynamicRef" 的值是 URI 參考,這使得將 schema 外部化或分割到多個文件中成為可能,並提供透過自我參考來驗證遞迴結構的能力。¶
這些關鍵字產生的已解析 URI 不一定是網路定位器,而只是一個識別符。如果 schema 是可網路定址的 URL,則不一定可以從該位址下載,並且實作不應假設它們在遇到可網路定址的 URI 時應執行網路操作。¶
"$ref" 關鍵字是一個應用程式,用於參考靜態識別的 schema。它的結果是所參考 schema 的結果。請注意,如何確定結果的此定義表示其他關鍵字可以與同一 schema 物件中的 "$ref" 一起出現。¶
"$ref" 關鍵字的值必須是一個字串,該字串是一個 URI 參考。針對目前的 URI 基礎進行解析,它會產生要套用的 schema 的 URI。此解析在載入 schema 時可以安全地執行,因為評估實例的過程不會改變參考的解析方式。¶
"$dynamicRef" 關鍵字是一個應用程式,允許將完整解析延遲到執行階段,屆時會在評估實例時每次遇到它時進行解析。¶
與 "$dynamicAnchor" 一起,"$dynamicRef" 實作了一種協作擴展機制,該機制主要用於遞迴 schema(參考自身的 schema)。擴展點和執行階段確定的擴展目標都是使用 "$dynamicAnchor" 定義的,並且僅在透過 "$dynamicRef" 參考時才會表現出執行階段的動態行為。¶
"$dynamicRef" 屬性的值必須是一個字串,該字串是一個 URI 參考。針對目前的 URI 基礎進行解析,它會產生用作執行階段解析起點的 URI。此初始解析在載入 schema 時可以安全地執行。¶
如果最初解析的起點 URI 包含由 "$dynamicAnchor" 關鍵字建立的片段,則初始 URI 必須替換為在 動態範圍 (第 7.1 節) 中定義了具有相同名稱的片段(使用 "$dynamicAnchor")的最外層 schema 資源的 URI(包括片段)。¶
否則,其行為與 "$ref" 相同,並且不需要執行階段解析。¶
有關使用這些關鍵字的完整範例,請參閱附錄 C。2019 年之前草案中的超 schema 中繼 schema 與本草案之間的差異顯著地展示了這些關鍵字的實用性。¶
"$defs" 關鍵字保留了一個位置,供 schema 作者將可重複使用的 JSON Schema 內嵌到更通用的 schema 中。該關鍵字不會直接影響驗證結果。¶
此關鍵字的值必須是一個物件。此物件的每個成員值都必須是一個有效的 JSON Schema。¶
例如,這是一個描述正整數陣列的 schema,其中正整數約束是 "$defs" 中的子 schema:¶
{ "type": "array", "items": { "$ref": "#/$defs/positiveInteger" }, "$defs": { "positiveInteger": { "type": "integer", "exclusiveMinimum": 0 } } }¶
此關鍵字保留了一個位置,用於 schema 作者向 schema 的讀者或維護者提供註解。¶
此關鍵字的值必須是一個字串。實作不得將此字串呈現給最終使用者。用於編輯 schema 的工具應支援顯示和編輯此關鍵字。此關鍵字的值可用於針對使用 schema 的開發人員的偵錯或錯誤輸出中。¶
Schema 詞彙應該允許在包含詞彙關鍵字的任何物件中使用 "$comment"。實作可以假設允許使用 "$comment",除非詞彙明確禁止使用。詞彙不得指定 "$comment" 超出本規範中所述的任何效果。¶
將其他媒體類型或程式語言與 application/schema+json 互相轉換的工具可以選擇將該媒體類型或程式語言的原生註解轉換為或從 "$comment" 值轉換。當原生註解和 "$comment" 屬性都存在時,此類轉換的行為取決於實作。¶
實作可以在處理過程中的任何時間點刪除 "$comment" 值。特別是,這允許在部署的 schema 大小是一個問題時縮短 schema。¶
實作不得根據 "$comment" 屬性的存在、缺失或內容採取任何其他動作。特別是,不得將 "$comment" 的值收集為註解結果。¶
RFC3986 第 5.1 節 [RFC3986] 定義了如何確定文件的預設基礎 URI。¶
一般而言,綱要的初始基礎 URI 是指找到該綱要時的 URI,無論是網路位置、本機檔案系統,或是任何其他可透過已知協定的 URI 來識別的情況。¶
如果綱要文件沒有使用 "$id"(嵌入於內容中)定義明確的基礎 URI,則基礎 URI 會根據 RFC 3986 第 5 節 [RFC3986] 的規定來決定。¶
如果來源不明,或來源的 URI 協定不明,則可以如 RFC 3986 第 5.1.4 節 [RFC3986] 所述,使用適合實作的預設 URI。建議實作文件記錄它們假設的任何預設基礎 URI。¶
如果綱要物件嵌入在另一種媒體類型的文件中,則初始基礎 URI 會根據該媒體類型的規則來決定。¶
除非較早章節中描述的 "$id" 關鍵字存在於根綱要中,否則此基礎 URI 應被視為綱要文件根綱要資源的標準 URI。¶
使用 URI 來識別遠端綱要並不一定意味著要下載任何內容,而是 JSON 綱要實作應該預先了解它們將使用哪些綱要,以及識別它們的 URI。¶
當綱要被下載時,例如由通用使用者代理程式在執行階段才知道要下載哪些綱要時,請參閱 超媒體的使用 (第 9.5.1 節)。¶
實作應該能夠將任意 URI 與任意綱要相關聯,和/或根據驗證器對綱要的信任程度,自動將綱要的 "$id" 給定的 URI 相關聯。這些 URI 和綱要可以在處理實例之前提供給實作,也可以在處理綱要文件時記錄,產生如附錄 A 中所示的關聯。¶
一個綱要可以(而且很可能)有多個 URI,但一個 URI 無法識別多個綱要。當多個綱要試圖識別為相同的 URI 時,驗證器應該提出錯誤條件。¶
如果因為另一個綱要的 "$schema" 關鍵字將綱要識別為元綱要而正在檢查該綱要,則實作必須將其識別為元綱要。這表示單一綱要文件有時可能被視為一般綱要,而有時則被視為元綱要。¶
在檢查本身即為元綱要的綱要時,當實作開始將其作為一般綱要處理時,將按照這些規則進行處理。但是,當由於檢查其自身的 "$schema" 值而第二次載入時,它將被視為元綱要。因此,同一個文件在一個會話過程中會以兩種方式處理。¶
實作可以允許將綱要明確地作為元綱要傳遞,用於特定於實作的目的,例如預先載入常用的元綱要並預先檢查其詞彙支援需求。元綱要作者不應期望此類功能在不同實作之間是可互通的。¶
綱要可以使用已給定的任何 URI 來識別,包括 JSON 指標或其 "$id" 直接給定的 URI。在所有情況下,取消 "$ref" 參考的參考首先涉及根據 RFC 3986 [RFC3986] 相對目前的基礎 URI 解析其值作為 URI 參考。¶
如果產生的 URI 識別出目前文件內或實作可用的另一個綱要文件內的綱要,則應該自動使用該綱要。¶
例如,考慮以下綱要:¶
{ "$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>,這未在此文件中定義。如果實作已以其他方式提供了具有該識別符的綱要,則也可以自動使用。當參考的綱要未知時,實作應該怎麼做?在哪些情況下允許自動網路取消參考?同源政策?使用者可設定的選項?在超綱要描述的演進式 API 的情況下,預期新綱要將動態新增到系統中,因此對預先載入綱要文件提出絕對要求是不可行的。¶
由於 JSON 指標 URI 片段是根據綱要文件的結構建構的,因此嵌入式綱要資源及其子綱要可以透過相對於其自身標準 URI 或相對於任何包含資源的 URI 的 JSON 指標片段來識別。¶
從概念上講,一組連結的綱要資源的行為應該相同,無論每個資源是使用 綱要參考 (第 8.2.3 節) 連接的獨立文件,還是結構化為單一文件,其中一個或多個綱要資源嵌入為子綱要。¶
由於當嵌入式綱要移動到獨立文件並被參考時,涉及相對於父綱要資源 URI 的 JSON 指標片段的 URI 會失效,因此應用程式和綱要不應使用此類 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": { } }¶
在這裡我們看到,使用附加到 "bar" 綱要資源的標準 URI 的 JSON 指標片段的 "https://example.com/bar#/additionalProperties" 仍然有效,而依賴於附加到 "foo" 綱要資源的標準 URI 的 JSON 指標片段的 "https://example.com/foo#/items/additionalProperties" 不再解析為任何內容。 ¶
另請注意,"https://example.com/foo#/items" 在兩種排列中都有效,但解析為不同的值。此 URI 的功能最終類似於資源的檢索 URI。雖然此 URI 有效,但除非特別希望在第二種(非嵌入式)排列中識別包含 "$ref" 的物件,否則使用嵌入式或參考資源的 "$id" 會更穩健。 ¶
實作可以選擇不支援使用資源標準 URI 以外的基礎 URI,加上相對於該基礎的 JSON 指標片段來尋址綱要資源內容。因此,綱要作者不應依賴此類 URI,因為使用它們可能會降低互通性。這是為了避免要求實作為每個 URI 保留一整疊可能的基礎 URI 和 JSON 指標片段的追蹤,因為如果綱要資源被重組,除了其中一個以外的所有 URI 都會變得脆弱。有些人認為這很容易,所以沒有必要禁止它,而另一些人則認為這會使綱要識別變得複雜,因此應該禁止。我們鼓勵對此主題提出意見。經過一些討論,我們認為需要刪除「標準」的使用,而改為談論跨綱要資源邊界的 JSON 指標,因為它們是未定義的,甚至是禁止的行為 (https://github.com/json-schema-org/json-schema-spec/issues/937, https://github.com/json-schema-org/json-schema-spec/issues/1183)¶
複合綱要文件定義為一個 JSON 文件(有時稱為「捆綁」綱要),其中多個嵌入式 JSON 綱要資源捆綁到同一個文件中,以方便傳輸。¶
每個嵌入式綱要資源必須被視為單獨的綱要資源,遵循標準綱要載入和處理要求,包括確定詞彙支援。¶
用於建立複合綱要文件的捆綁流程定義為取得對外部綱要資源的參考(例如 "$ref"),並將參考的綱要資源嵌入到參考文件中。捆綁應該以這樣的方式完成,使得基礎文件和任何參考/嵌入的文件中使用的所有 URI(用於參考)都不需要更改。¶
每個嵌入式 JSON 綱要資源必須使用 "$id" 關鍵字以 URI 識別自身,並且應該在綱要資源的根中使用 "$schema" 關鍵字來識別其使用的方言。建議 "$id" 的 URI 識別符值為絕對 URI。¶
當以參照方式套用的應用程式所參照的綱要資源被捆綁時,建議將該綱要資源放置在包含綱要根目錄的 "$defs" 物件的值中。現在嵌入的綱要資源的 "$defs" 的鍵可以是捆綁綱要的 "$id",或是其他應用程式定義的唯一識別符 (例如 UUID)。此鍵並非旨在於 JSON 綱要中被參照,但應用程式可以使用它來輔助捆綁過程。¶
綱要資源可以嵌入在 "$defs" 以外的位置,其中該位置被定義為綱要值。¶
捆綁的綱要資源不得透過取代它所參照的綱要物件,或將該綱要資源包裝在其他應用程式關鍵字中來捆綁。¶
為了產生相同的輸出,包含綱要文件中先前對外部綱要資源的參照不得變更,且現在應解析為使用嵌入綱要資源的 "$id" 的綱要。此相同的輸出包含驗證評估和在結果註解或錯誤中使用的 URI 或路徑。¶
雖然捆綁過程通常是建立複合綱要文件 (Compound Schema Document) 的主要方法,但也可能且預期會有一些複合綱要文件是手動建立的,可能之前沒有個別存在的綱要資源。¶
當單一文件中存在多個綱要資源時,未定義應使用哪種方言處理的綱要資源必須使用與封閉資源相同的方言進行處理。¶
由於任何可被參照的綱要都可以被嵌入,因此嵌入的綱要資源可以使用其封閉資源中的 "$schema" 值來指定不同的處理方言。¶
由於複合綱要文件可能具有嵌入的資源,這些資源識別為使用不同的方言,因此不應透過將中繼綱要 (meta-schema) 作為實例應用於複合綱要文件來驗證這些文件。建議提供替代驗證過程以驗證綱要文件。每個綱要資源都應根據其相關的中繼綱要單獨驗證。如果您知道正在驗證的是綱要,則可以透過使用 "$id" 來識別綱要是否為複合綱要文件,當 "$id" 不在文件的根目錄中使用時,則會識別嵌入的資源。¶
當所有嵌入資源都識別為使用相同方言,或省略 "$schema" 並因此預設為封閉資源的方言時,可以使用適當的中繼綱要來驗證複合綱要文件。¶
綱要不得針對實例進入無限迴圈。例如,如果兩個綱要 "#alice" 和 "#bob" 都有一個 "allOf" 屬性參照另一個,則天真的驗證器可能會在嘗試驗證實例時陷入無限遞迴迴圈。綱要不應使用這種無限遞迴巢狀結構;此行為未定義。¶
子綱要物件 (或布林值) 是透過其與已知應用程式關鍵字或保留位置的關鍵字 (例如 "$defs" (第 8.2.4 節),它們將一個或多個子綱要作為值) 的使用來識別。這些關鍵字可能是 "$defs" 和本文檔中的標準應用程式關鍵字,或是已知詞彙表的擴展關鍵字,或是特定於實作的自訂關鍵字。¶
未知關鍵字的多層結構能夠引入巢狀子綱要,這些子綱要將受制於 "$id" 的處理規則。因此,在這種無法識別的結構中設定參照目標無法可靠地實作,並且產生的行為未定義。同樣地,已知關鍵字下的參照目標 (其值已知不是綱要) 會導致未定義的行為,以避免實作需要檢測此類目標。 這些情況類似於透過 HTTP 擷取綱要,但收到 Content-Type 不是 application/schema+json 的回應。實作當然可以嘗試將其解釋為綱要,但來源伺服器並未保證它實際上是任何此類綱要。因此,將其解釋為綱要具有安全性隱患,並可能產生不可預測的結果。¶
請注意,具有與 "$defs" 相同語法和語意的單層自訂關鍵字不允許任何中間的 "$id" 關鍵字,因此在嘗試將任何參照目標用作綱要的實作下,其行為將正確。但是,此行為是特定於實作的,不得依賴其互操作性。¶
JSON 已被 HTTP 伺服器廣泛採用於自動化 API 和機器人。本節介紹如何在與支援媒體類型和 Web 連結 [RFC8288] 的協定一起使用時,以更符合 RESTful 風格的方式增強 JSON 文件的處理。¶
建議由綱要描述的實例使用連結關係 "describedby" 提供可下載的 JSON 綱要連結,如 Linked Data Protocol 1.0, 第 8.1 節 [W3C.REC-ldp-20150226] 中所定義。¶
在 HTTP 中,可以使用 Link 標頭 [RFC8288] 將此類連結附加到任何回應。此類標頭的範例為:¶
Link: <https://example.com/my-hyper-schema>; rel="describedby"¶
在網路上的超媒體系統中使用時,HTTP [RFC7231] 通常是分發綱要的首選協定。如果用戶端從網路提取綱要的頻率高於必要頻率,則可能會對伺服器維護者造成問題,而實際上可以將綱要快取一段時間。¶
HTTP 伺服器應在 JSON 綱要上設定長期快取標頭。HTTP 用戶端應觀察快取標頭,並且在其新鮮期內不重新請求文件。分散式系統應使用共用快取和/或快取代理。¶
用戶端應設定或預先加入特定於 JSON 綱要實作或軟體產品的 User-Agent 標頭。由於符號依重要性遞減的順序列出,因此 JSON 綱要程式庫名稱/版本應位於較通用的 HTTP 程式庫名稱 (如果有的話) 之前。例如:¶
User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0¶
用戶端應能夠使用 "From" 標頭發出請求,以便伺服器操作員可以聯絡可能行為不端的腳本擁有者。¶
本節定義了一組應用程式關鍵字的詞彙表,建議用作其他詞彙表的基礎。¶
不使用 "$vocabulary" 的中繼綱要應被視為需要此詞彙表,就像其 URI 以 true 值存在一樣。¶
此詞彙表 (稱為應用程式詞彙表) 的目前 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/applicator>。¶
對應的中繼綱要的目前 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/applicator。¶
綱要關鍵字通常獨立運作,不會影響彼此的結果。¶
為了方便綱要作者,此詞彙表中的關鍵字有一些例外:¶
這些關鍵字將子綱要應用到與套用父綱要的實例相同位置。它們允許以各種方式組合或修改子綱要結果。¶
這些關鍵字的子綱要會完全獨立地評估實例,因此一個此類子綱要的結果不得影響同級子綱要的結果。因此,子綱要可以依任何順序應用。¶
這些關鍵字對應於用於組合或修改子模式的布林斷言結果的邏輯運算符。它們對註解收集沒有直接影響,儘管它們允許將相同的註解關鍵字應用於具有不同值的實例位置。註解關鍵字定義了它們自己的組合這些值的規則。¶
此關鍵字的值必須是一個非空陣列。陣列的每個項目都必須是一個有效的 JSON Schema。¶
如果實例針對此關鍵字的值所定義的所有模式都成功驗證,則該實例針對此關鍵字成功驗證。¶
此關鍵字的值必須是一個非空陣列。陣列的每個項目都必須是一個有效的 JSON Schema。¶
如果實例針對此關鍵字的值所定義的至少一個模式成功驗證,則該實例針對此關鍵字成功驗證。請注意,當收集註解時,必須檢查所有子模式,以便從每個成功驗證的子模式中收集註解。¶
此關鍵字的值必須是一個非空陣列。陣列的每個項目都必須是一個有效的 JSON Schema。¶
如果實例針對此關鍵字的值所定義的恰好一個模式成功驗證,則該實例針對此關鍵字成功驗證。¶
這些關鍵字中的三個協同工作,以基於另一個子模式的結果來實現子模式的有條件應用。第四個是特定條件情況的捷徑。¶
「if」、「then」和「else」不得在子模式邊界之間相互影響。換句話說,「allOf」的一個分支中的「if」不得對另一個分支中的「then」或「else」產生影響。¶
當「if」、「then」或「else」不存在時,沒有預設行為。特別是,它們不得被視為存在並具有空模式,並且當「if」不存在時,「then」和「else」都必須完全忽略。¶
此關鍵字的值必須是一個有效的 JSON Schema。¶
此關鍵字的子模式的驗證結果對整體驗證結果沒有直接影響。相反,它控制評估「then」或「else」關鍵字中的哪一個。¶
針對此關鍵字的子模式成功驗證的實例也必須針對「then」關鍵字的子模式值有效(如果存在)。¶
未能針對此關鍵字的子模式成功驗證的實例也必須針對「else」關鍵字的子模式值有效(如果存在)。¶
如果正在收集註解(第 7.7 節),則以通常方式從此關鍵字的子模式中收集,包括當關鍵字存在但沒有「then」或「else」時。¶
此關鍵字的值必須是一個有效的 JSON Schema。¶
當「if」存在,並且實例針對其子模式成功驗證時,如果實例也針對此關鍵字的子模式成功驗證,則針對此關鍵字的驗證成功。¶
當「if」不存在時,或當實例未能針對其子模式成功驗證時,此關鍵字沒有效果。在這種情況下,為了驗證或註解收集的目的,實作必須不要針對此關鍵字評估實例。¶
此關鍵字的值必須是一個有效的 JSON Schema。¶
當「if」存在,並且實例未能針對其子模式成功驗證時,如果實例針對此關鍵字的子模式成功驗證,則針對此關鍵字的驗證成功。¶
當「if」不存在時,或當實例針對其子模式成功驗證時,此關鍵字沒有效果。在這種情況下,為了驗證或註解收集的目的,實作必須不要針對此關鍵字評估實例。¶
如果實例是一個物件並且包含某個屬性,則此關鍵字指定要評估的子模式。¶
此關鍵字的值必須是一個物件。物件中的每個值都必須是一個有效的 JSON Schema。¶
如果物件鍵是實例中的一個屬性,則整個實例必須針對子模式進行驗證。它的使用取決於屬性的存在。¶
省略此關鍵字的行為與空物件相同。¶
這些關鍵字中的每一個都定義了一條規則,用於將其子模式應用於子實例(特別是物件屬性和陣列項目)並組合其結果。¶
「prefixItems」的值必須是一個非空的有效 JSON Schema 陣列。¶
如果實例的每個元素針對相同位置的模式(如果有的話)進行驗證,則驗證成功。此關鍵字不約束陣列的長度。如果陣列比此關鍵字的值長,則此關鍵字僅驗證匹配長度的前綴。¶
此關鍵字產生一個註解值,該值是此關鍵字應用子模式的最大索引。如果子模式已應用於實例的每個索引,則該值可以是一個布林值 true,例如「items」關鍵字產生的值。此註解會影響「items」和「unevaluatedItems」的行為。¶
省略此關鍵字的斷言行為與空陣列相同。¶
「items」的值必須是一個有效的 JSON Schema。¶
此關鍵字將其子模式應用於同一模式物件中「prefixItems」陣列長度之後的索引處的所有實例元素,如該「prefixItems」關鍵字的註解結果所報告的那樣。如果不存在此類註解結果,「items」將其子模式應用於所有實例陣列元素。請注意,「items」在沒有「prefixItems」的情況下的行為與先前草案中「items」的模式形式相同。當存在「prefixItems」時,「items」的行為與之前的「additionalItems」關鍵字相同。¶
如果「items」子模式應用於實例陣列中的任何位置,它將產生一個布林值 true 的註解結果,表示所有剩餘的陣列元素都已針對此關鍵字的子模式進行評估。此註解會影響未評估詞彙中「unevaluatedItems」的行為。¶
省略此關鍵字的斷言行為與空模式相同。¶
實作可以選擇以另一種方式實現或最佳化此關鍵字,以產生相同的效果,例如直接檢查「prefixItems」陣列的存在和大小。不支援註解收集的實作必須這樣做。¶
此關鍵字的值必須是一個有效的 JSON Schema。¶
如果陣列實例中至少有一個元素針對給定的模式有效,則該陣列實例針對「contains」有效,除非「minContains」存在且值為 0,在這種情況下,即使沒有任何元素針對給定的模式有效,陣列實例也必須被視為針對「contains」關鍵字有效。¶
此關鍵字產生一個註解值,該值是一個陣列,其中包含此關鍵字在應用其子模式時成功驗證的索引(按升序排列)。如果子模式在應用於實例的每個索引時都成功驗證,則該值可以是一個布林值「true」。如果應用此關鍵字模式的實例陣列為空,則必須存在註解。¶
此註解會影響未評估詞彙中「unevaluatedItems」的行為,並且也可以用於實現驗證詞彙中的「minContains」和「maxContains」關鍵字。¶
為了收集其他關鍵字使用的註解,即使在找到第一個匹配項之後,也必須將子模式應用於每個陣列元素。這是為了確保收集所有可能的註解。¶
"properties" 的值必須是一個物件。此物件的每個值都必須是有效的 JSON Schema。¶
如果實例中出現的每個名稱,同時也做為此關鍵字的值內的名稱出現,則該名稱的子實例成功地根據對應的模式進行驗證,則驗證成功。¶
此關鍵字的註解結果是此關鍵字所匹配的實例屬性名稱的集合。此註解會影響「additionalProperties」(在此詞彙表中)和 Unevaluated 詞彙表中的「unevaluatedProperties」的行為。¶
省略此關鍵字與空物件具有相同的斷言行為。¶
"patternProperties" 的值必須是一個物件。此物件的每個屬性名稱都應該是有效的正規表示式,根據 ECMA-262 正規表示式方言。此物件的每個屬性值都必須是有效的 JSON Schema。¶
如果每個實例名稱都符合此關鍵字值中做為屬性名稱出現的任何正規表示式,則該名稱的子實例成功地根據每個符合的正規表示式所對應的模式進行驗證,則驗證成功。¶
此關鍵字的註解結果是此關鍵字所匹配的實例屬性名稱的集合。此註解會影響「additionalProperties」(在此詞彙表中)和「unevaluatedProperties」(在 Unevaluated 詞彙表中)的行為。¶
省略此關鍵字與空物件具有相同的斷言行為。¶
"additionalProperties" 的值必須是有效的 JSON Schema。¶
此關鍵字的行為取決於同一個模式物件中「properties」和「patternProperties」的存在及其註解結果。「additionalProperties」的驗證僅適用於實例名稱的子值,這些子值沒有出現在「properties」或「patternProperties」的任一註解結果中。¶
對於所有這類屬性,如果子實例根據「additionalProperties」模式進行驗證,則驗證成功。¶
此關鍵字的註解結果是由此關鍵字的子模式驗證的實例屬性名稱的集合。此註解會影響 Unevaluated 詞彙表中的「unevaluatedProperties」的行為。¶
省略此關鍵字與空模式具有相同的斷言行為。¶
實作可以選擇以其他方式實作或最佳化此關鍵字,以產生相同的效果,例如直接針對實例屬性集檢查「properties」中的名稱和「patternProperties」中的模式。不支援註解收集的實作必須這麼做。在定義此選項時,輸出格式似乎存在潛在的模糊性。模糊性不會影響驗證結果,但會影響最終的輸出格式。模糊性允許根據是否使用註解,或使用與草案 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" 的值必須是有效的 JSON Schema。¶
如果實例是一個物件,則如果實例中的每個屬性名稱都根據提供的模式進行驗證,則此關鍵字會驗證成功。請注意,模式正在測試的屬性名稱將永遠是一個字串。¶
省略此關鍵字與空模式具有相同的行為。¶
這些關鍵字的目的是讓模式作者能夠將子模式應用於陣列項目或物件屬性,這些項目或屬性尚未根據任何相鄰關鍵字的任何動態範圍子模式成功評估。¶
這些實例項目或屬性可能未成功地根據一個或多個相鄰關鍵字子模式進行評估,例如當「anyOf」分支中的斷言失敗時。這種失敗的評估不被認為有助於判斷該項目或屬性是否已評估。僅考慮成功的評估。¶
如果陣列中的項目或物件屬性被「成功評估」,則從邏輯上來說,會被認為就預期的物件或陣列的表示形式而言是有效的。例如,如果子模式表示一輛車,該車需要 2-4 個輪子,而「wheels」的值為 6,則實例物件不會被「評估」為一輛車,而「wheels」屬性被視為「未評估(成功地作為已知的東西)」,並且不保留任何註解。¶
回想一下,相鄰關鍵字是同一個模式物件中的關鍵字,而動態範圍子模式包括參考目標以及詞彙子模式。¶
這些關鍵字的行為取決於適用於要驗證的實例位置的相鄰關鍵字的註解結果。¶
不使用「$vocabulary」的 Meta 模式應被視為要求此詞彙表,就像其 URI 以 true 值存在一樣。¶
此詞彙表(稱為未評估應用程式詞彙表)的目前 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/unevaluated>。¶
相應的 Meta 模式的目前 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/unevaluated。¶
模式關鍵字通常獨立運作,不會影響彼此的結果。但是,此詞彙表中的關鍵字是顯著的例外:¶
「unevaluatedItems」的值必須是有效的 JSON Schema。¶
此關鍵字的行為取決於適用於要驗證的實例位置的相鄰關鍵字的註解結果。具體來說,來自「prefixItems」、「items」和「contains」的註解,這些註解可以來自相鄰於「unevaluatedItems」關鍵字時的那些關鍵字。這三個註解以及「unevaluatedItems」,也可能來自任何及所有相鄰的就地應用程式 (第 10.2 節)關鍵字。這包括但不限於本文檔中定義的就地應用程式。¶
如果沒有相關的註解,則「unevaluatedItems」子模式必須應用於陣列中的所有位置。如果任何相關註解中存在布林值 true,則必須忽略「unevaluatedItems」。否則,子模式必須應用於任何大於「prefixItems」最大註解值的索引,該索引不會出現在任何「contains」的註解值中。¶
這表示必須先評估「prefixItems」、「items」、「contains」和所有就地應用程式,才能評估此關鍵字。擴充關鍵字的作者不得定義需要在評估此關鍵字後才能評估的就地應用程式。¶
如果「unevaluatedItems」子模式應用於實例陣列中的任何位置,則會產生布林值 true 的註解結果,與「items」的行為類似。此註解會影響父模式中「unevaluatedItems」的行為。¶
省略此關鍵字與空模式具有相同的斷言行為。¶
「unevaluatedProperties」的值必須是有效的 JSON Schema。¶
此關鍵字的行為取決於適用於要驗證的實例位置的相鄰關鍵字的註解結果。具體來說,來自「properties」、「patternProperties」和「additionalProperties」的註解,這些註解可以來自相鄰於「unevaluatedProperties」關鍵字時的那些關鍵字。這三個註解以及「unevaluatedProperties」,也可能來自任何及所有相鄰的就地應用程式 (第 10.2 節)關鍵字。這包括但不限於本文檔中定義的就地應用程式。¶
「unevaluatedProperties」的驗證僅適用於實例名稱的子值,這些子值沒有出現在適用於要驗證的實例位置的「properties」、「patternProperties」、「additionalProperties」或「unevaluatedProperties」註解結果中。¶
對於所有這類屬性,如果子實例根據「unevaluatedProperties」模式進行驗證,則驗證成功。¶
這表示必須先評估「properties」、「patternProperties」、「additionalProperties」和所有就地應用程式,才能評估此關鍵字。擴充關鍵字的作者不得定義需要在評估此關鍵字後才能評估的就地應用程式。¶
此關鍵字的註解結果是由此關鍵字的子模式驗證的實例屬性名稱的集合。此註解會影響父模式中「unevaluatedProperties」的行為。¶
省略此關鍵字與空模式具有相同的斷言行為。¶
JSON Schema 被定義為平台獨立。因此,為了提高跨平台的相容性,實作應該符合標準的驗證輸出格式。本節說明消費者正確解讀驗證結果所需的最基本要求。¶
JSON Schema 的輸出是使用 JSON Schema 資料實例模型定義的,如第 4.2.1 節所述。 實作方式可以根據其特定語言和平台而有所不同,但建議輸出可以透過序列化或其他方式轉換為此處定義的 JSON 格式。¶
本規範定義了四種輸出格式。 請參閱「輸出結構」部分,了解每種格式的要求。¶
實作方式應至少提供「旗標 (flag)」、「基本 (basic)」或「詳細 (detailed)」格式之一,且可以提供「詳細 (verbose)」格式。 如果實作方式提供「詳細 (detailed)」或「詳細 (verbose)」格式中的一或多種,則也必須提供「旗標 (flag)」格式。 實作方式應在其文件中指定它們支援哪些格式。¶
除了簡單的「旗標 (flag)」輸出之外,額外的資訊對於協助偵錯綱要或實例很有用。每個子結果應至少包含本節中包含的資訊。¶
包含所有這些元件的單一物件被視為一個輸出單元。¶
實作方式可以選擇提供額外資訊。¶
驗證路徑之後的驗證關鍵字的相對位置。該值必須表示為 JSON 指標,並且必須包含任何透過參考的應用程式,例如「$ref」或「$dynamicRef」。¶
/properties/width/$ref/minimum¶
請注意,由於包含這些透過參考的應用程式關鍵字,因此此指標可能無法透過一般的 JSON 指標流程解析。¶
此資訊的 JSON 索引鍵為「keywordLocation」。¶
驗證關鍵字的絕對、取消參考的位置。該值必須表示為使用相關綱要資源的標準 URI 的完整 URI,並包含 JSON 指標片段,並且不得包含透過參考的應用程式,例如「$ref」或「$dynamicRef」作為非終端路徑元件。如果錯誤或註釋是針對該關鍵字(例如無法解析的參考),則可以以這類關鍵字結尾。請注意,此處的「絕對」是指「絕對檔案系統路徑」(表示完整位置),而不是 RFC 3986 中的「絕對 URI」術語(表示帶有綱要但不帶片段)。關鍵字絕對位置將具有片段,以便識別關鍵字。¶
https://example.com/schemas/common#/$defs/count/minimum¶
只有在動態範圍未通過參考,或綱要未將絕對 URI 宣告為其「$id」時,才可以省略此資訊。¶
此資訊的 JSON 索引鍵為「absoluteKeywordLocation」。¶
要驗證的實例中 JSON 值的位置。該值必須表示為 JSON 指標。¶
此資訊的 JSON 索引鍵為「instanceLocation」。¶
驗證產生的錯誤或註釋。¶
對於錯誤,本規範未定義訊息的具體措辭。 實作方式需要提供此項。¶
對於註釋,產生註釋的每個關鍵字都會指定其格式。預設情況下,它是關鍵字的值。¶
失敗驗證的 JSON 索引鍵為「error」;成功驗證的 JSON 索引鍵為「annotation」。¶
對於兩個階層式結構,此屬性將保留巢狀錯誤和註釋。¶
失敗驗證中巢狀結果的 JSON 索引鍵為「errors」;成功驗證中巢狀結果的 JSON 索引鍵為「annotations」。請注意複數形式,因為具有巢狀結果的關鍵字也可能具有本機錯誤或註釋。¶
輸出必須是一個物件,其中包含一個名為「valid」的布林值屬性。 當需要有關結果的額外資訊時,輸出也必須包含如下所述的「errors」或「annotations」。¶
在這些範例中,將使用以下綱要和實例。¶
{ "$id": "https://example.com/polygon", "$schema": "https://json-schema.dev.org.tw/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 } ]¶
此實例將無法通過驗證並產生錯誤,但要推斷出產生註釋的通過綱要的範例是很簡單的。¶
具體來說,它將產生的錯誤是:¶
請注意,這些範例中描述的錯誤訊息措辭不是本規範的要求。 實作方式應針對其受眾量身打造錯誤訊息,或提供允許其使用者製作自己的訊息的範本機制。¶
在最簡單的情況下,僅需要滿足「valid」有效屬性的布林值結果。¶
{ "valid": false }¶
由於此格式未傳回任何錯誤或註釋,因此建議實作方式使用短路邏輯,以便在可以確定結果時立即傳回失敗或成功。 例如,如果「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)」結構基於綱要,對於人類和機器而言都更具可讀性。以這種方式組織結構可以使錯誤之間的關聯更加明顯。 例如,在「基本 (Basic)」結構中,遺失的「y」屬性和額外的「z」屬性都源自實例中的相同位置,這一事實並不明顯。 在階層中,可以更容易地識別相關性。¶
以下規則控管結果物件的建構:¶
分支節點不需要錯誤訊息或註釋。¶
{ "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` 關鍵字內成功的驗證等)。 因此,建議每個節點也都帶有一個 `valid` 屬性,以指示該節點的驗證結果。¶
由於此輸出結構可能非常大,因此此處提供一個較小的範例以簡潔起見。 上述範例完整輸出結構的 URI 為:https://json-schema.dev.org.tw/draft/2020-12/output/verbose-example。¶
// schema { "$id": "https://example.com/polygon", "$schema": "https://json-schema.dev.org.tw/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.dev.org.tw/draft/2020-12/output/schema。¶
綱要和實例都是 JSON 值。 因此,適用於 RFC 8259 [RFC8259] 中定義的所有安全考量。¶
實例和綱要通常都是由不受信任的協力廠商編寫,以部署在公共網際網路伺服器上。 驗證程式應注意,針對綱要進行剖析和驗證時不會耗用過多的系統資源。 驗證程式絕不能陷入無限迴圈。¶
惡意方可能會導致實作方式重複收集非常大的值作為註釋的副本。 在這種情況下,實作方式應防範過度耗用系統資源。¶
伺服器必須確保惡意方無法透過上傳具有先前存在或非常相似的「$id」的綱要來變更現有綱要的功能。¶
個別的 JSON Schema 詞彙也可能具有自己的安全考量。 如需更多資訊,請參閱各自的規格。¶
綱要作者應注意「$comment」內容,因為惡意實作方式可能會違反規格向最終使用者顯示這些內容,或者在預期此行為時未能移除這些內容。¶
惡意綱要作者可能會在「$comment」中放置可執行程式碼或其他危險材料。 實作方式絕不能根據「$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 指標 [RFC6901](相對於根綱要)中的綱要具有以下基本 URI,並且可依照上述第 5 節和第 9.2.1 節的規定,通過任何列出的 URI 識別。¶
注意:URI 的片段部分並不會使其成為標準或非標準,而是所使用的基本 URI(作為帶有任何片段的完整 URI 的一部分)決定了所產生完整 URI 的標準性質。多個「標準」URI?我們承認這可能會造成混淆,並請您閱讀位於JSON 指標片段和嵌入式綱要資源(第 9.2.1 節)章節中的 CREF,以取得進一步的評論。¶
已建立各種工具,可根據參考(「$ref」)出現的方式和位置重新排列綱要文件。此附錄討論哪些使用案例和動作符合本規格。¶
一組預期一起使用的 schema 資源,可以將每個資源放在自己的 schema 文件中,全部放在同一個 schema 文件中,或是介於兩者之間的任何文件分組粒度。¶
有許多工具可以執行各種參考移除。常見的情況是產生一個單一檔案,其中所有參考都可以在該檔案內解析。這通常是為了簡化分發,或是簡化編碼,讓 JSON Schema 函式庫的各種呼叫不需要追蹤和載入大量的資源。¶
只要所有靜態參考(例如 "$ref")使用 URI 參考,解析為以規範資源 URI 作為基礎的 URI,並且所有 schema 資源在其根 schema 中都有一個絕對 URI 作為 "$id",就可以安全且可逆地完成此轉換。¶
在滿足這些條件的情況下,每個外部資源都可以複製到 "$defs" 下,而不會破壞資源 schema 物件之間的任何參考,也不會改變驗證或註解結果的任何方面。 "$defs" 下的 schema 名稱不會影響行為,假設它們各自都是唯一的,因為它們不會出現在嵌入資源的規範 URI 中。¶
嘗試移除所有參考並產生單一 schema 文件,在所有情況下,並不會產生與原始形式具有相同行為的 schema。¶
由於 "$ref" 現在被視為任何其他關鍵字,並且允許在同一個 schema 物件中使用其他關鍵字,因此在所有情況下完全支援非遞迴的 "$ref" 移除可能需要相對複雜的 schema 操作。確定或提供一組安全的 "$ref" 移除轉換超出本規範的範圍,因為它們不僅取決於 schema 結構,還取決於預期的用法。¶
考慮以下兩個 schema,描述一個簡單的遞迴樹狀結構,其中樹中的每個節點都可以有一個任何類型的「data」欄位。第一個 schema 允許並忽略其他實例屬性。第二個則更嚴格,只允許「data」和「children」屬性。也顯示了一個「data」拼寫錯誤為「daat」的實例範例。¶
// tree schema, extensible { "$schema": "https://json-schema.dev.org.tw/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.dev.org.tw/draft/2020-12/schema", "$id": "https://example.com/strict-tree", "$dynamicAnchor": "node", "$ref": "tree", "unevaluatedProperties": false } // instance with misspelled field { "children": [ { "daat": 1 } ] }¶
當我們載入這兩個 schema 時,我們會注意到每個 schema 中都存在名為「node」的 "$dynamicAnchor"(請注意,缺少 "#",因為這只是名稱),導致以下完整 schema URI:¶
此外,JSON Schema 實作會追蹤這些片段是使用 "$dynamicAnchor" 建立的事實。¶
如果我們將「strict-tree」schema 應用於實例,我們將會追蹤 "$ref" 到「tree」schema,檢查它的「children」子 schema,並在其「items」子 schema 中找到 "$dynamicRef":到 "#node"(請注意 URI 片段語法的 "#")。該參考解析為「https://example.com/tree#node」,這是一個由 "$dynamicAnchor" 建立的片段的 URI。因此,我們必須在追蹤參考之前檢查動態範圍。¶
此時,動態路徑為 "#/$ref/properties/children/items/$dynamicRef",動態範圍包含(從最外層範圍到最內層):¶
由於我們正在尋找一個純名稱片段,該片段可以在 schema 資源中的任何位置定義,因此 JSON 指標片段與此檢查無關。這意味著我們可以移除這些片段並消除連續重複項,產生:¶
在這種情況下,最外層資源也具有由 "$dynamicAnchor" 定義的「node」片段。因此,我們不是將 "$dynamicRef" 解析為「https://example.com/tree#node」,而是將其解析為「https://example.com/strict-tree#node」。¶
這樣, 「tree」schema 中的遞迴會遞迴到「strict-tree」的根,而不是僅將「strict-tree」應用於實例根,而是將「tree」應用於實例子節點。¶
這個例子顯示了每個 schema 中相同位置的 "$dynamicAnchor",特別是資源根 schema。由於純名稱片段與 JSON 結構無關,如果一個或兩個節點 schema 物件被移動到 "$defs" 下,這也同樣有效。是符合的 "$dynamicAnchor" 值告訴我們如何解析動態參考,而不是 JSON 結構中的任何關聯性。¶
如果詞彙表預期廣泛使用,並可能與其他詞彙表組合,詞彙表作者應注意避免關鍵字名稱衝突。JSON Schema 沒有提供任何正式的命名空間系統,但也沒有限制關鍵字名稱,允許使用任何數量的命名空間方法。¶
詞彙表可以相互建構,例如,定義其關鍵字相對於另一個詞彙表中的關鍵字的行為,或是使用另一個詞彙表中的關鍵字,並具有一組受限或擴展的可接受值。並非所有此類詞彙表重複使用都會產生一個與其建構所基於的詞彙表相容的新詞彙表。詞彙表作者應清楚地記錄預期的任何相容性層級。¶
元 schema 作者不應使用 "$vocabulary" 來組合多個為相同關鍵字定義衝突語法或語義的詞彙表。由於語義衝突通常無法通過 schema 驗證檢測到,因此不期望實作檢測到此類衝突。如果宣告了衝突的詞彙表,則產生的行為是未定義的。¶
詞彙表作者應提供一個元 schema,該元 schema 會驗證詞彙表關鍵字本身的預期用法。此類元 schema 不應禁止其他關鍵字,並且不得禁止核心詞彙表中的任何關鍵字。¶
建議元 schema 作者使用 "allOf" (第 10.2.1.1 節) 關鍵字參考每個詞彙表的元 schema,儘管其他用於建構元 schema 的機制可能適用於某些用例。¶
元 schema 的遞迴性質使得 "$dynamicAnchor" 和 "$dynamicRef" 關鍵字對於擴展現有的元 schema 特別有用,正如在擴展驗證元 schema 的 JSON 超級 schema 元 schema 中所見。¶
元 schema 可以施加額外的約束,包括描述任何詞彙表中不存在的關鍵字,超出與宣告的詞彙表相關聯的元 schema 所描述的範圍。這允許將用法限制為詞彙表的子集,並驗證不打算重複使用的本地定義的關鍵字。¶
但是,元 schema 不應與它們宣告的任何詞彙表相矛盾,例如要求與詞彙表預期的 JSON 類型不同的類型。產生的行為是未定義的。¶
用於本地使用,無需測試任意實作中的詞彙表支援的元 schema,可以安全地完全省略 "$vocabulary"。 ¶
此元 schema 明確宣告了核心和應用程式詞彙表,以及一個擴展詞彙表,並將它們的元 schema 與 "allOf" 組合。擴展詞彙表的元 schema(僅描述該詞彙表中的關鍵字)顯示在主要範例元 schema 之後。¶
主要範例元 schema 也透過禁止以「unevaluated」為前綴的關鍵字來限制未評估詞彙表的用法,這些關鍵字特別難以實作。這不會改變其他詞彙表所定義的語義或關鍵字集。它只是確保使用此元 schema 的嘗試使用以「unevaluated」為前綴的關鍵字的 schema 將無法通過此元 schema 的驗證。¶
最後,此元 schema 描述了一個關鍵字「localKeyword」的語法,該關鍵字不屬於任何詞彙表。據推測,此元 schema 的實作者和使用者將了解「localKeyword」的語義。JSON Schema 沒有定義任何用於表達詞彙表以外的關鍵字語義的機制,因此它們不適用於特定環境中使用,在這種環境中它們會被理解。¶
此元 schema 結合了多個詞彙表以供一般使用。¶
{ "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "$id": "https://example.com/meta/general-use-example", "$dynamicAnchor": "meta", "$vocabulary": { "https://json-schema.dev.org.tw/draft/2020-12/vocab/core": true, "https://json-schema.dev.org.tw/draft/2020-12/vocab/applicator": true, "https://json-schema.dev.org.tw/draft/2020-12/vocab/validation": true, "https://example.com/vocab/example-vocab": true }, "allOf": [ {"$ref": "https://json-schema.dev.org.tw/draft/2020-12/meta/core"}, {"$ref": "https://json-schema.dev.org.tw/draft/2020-12/meta/applicator"}, {"$ref": "https://json-schema.dev.org.tw/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 僅描述一個擴展詞彙表。¶
{ "$schema": "https://json-schema.dev.org.tw/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", } } }¶
如上所示,即使在通用元 schema 的 "allOf" 中參考的每個單一詞彙表元 schema 都宣告其對應的詞彙表,此新的元 schema 也必須重新宣告它們。¶
組合核心和驗證規範定義的所有詞彙表的標準元 schema,以及組合這些規範以及超級 schema 規範定義的所有詞彙表的標準元 schema,展示了更複雜的組合。這些元 schema 的 URI 可以分別在驗證和超級 schema 規範中找到。¶
雖然通用元 schema 可以驗證「minDate」的語法,但它是定義「minDate」語義含義背後邏輯的詞彙表。如果沒有對語義的理解(在此範例中,實例值必須是等於或晚於 schema 中提供為關鍵字值的日期),實作只能驗證語法用法。在這種情況下,這意味著驗證它是一個日期格式的字串(使用「pattern」來確保即使「format」僅作為註解功能時也能進行驗證,如 驗證規範 [json-schema-validation] 中所述)。¶
雖然預期參考的存在對於驗證結果是透明的,但諸如程式碼產生器和 UI 渲染器之類的產生式用例通常會認為參考在語義上很重要。¶
為了使此類特定於用例的語義明確,最佳實務是在與諸如 "$ref" 之類的參考關鍵字相同的 schema 物件中建立一個註解關鍵字。¶
例如,這是一個假設的關鍵字,用於確定程式碼產生器是否應將參考目標視為一個不同的類別,以及這些類別之間的關聯方式。請注意,此範例僅用於說明目的,並不打算提出一個功能性的程式碼產生關鍵字。¶
{ "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", } } }¶
在此,此 schema 表示某種類型的物件導向類別。"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 狀態前移除。¶