網際網路工程任務組 A. Wright,編輯
網路草案
預定狀態:資訊性 H. Andrews,編輯
截止日期:2020 年 3 月 20 日
B. Hutton,編輯
Wellcome Sanger 研究所
G. Dennis
2019 年 9 月 17 日

JSON Schema:用於描述 JSON 文件的媒體類型
draft-handrews-json-schema-02

摘要

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/。

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

本網路草案將於 2020 年 3 月 20 日到期。

著作權聲明

版權所有 (c) 2019 IETF Trust 和被認定為文件作者的人員。保留所有權利。

本文件受 BCP 78 和 IETF Trust 的《關於 IETF 文件的法律規定》(https://trustee.ietf.org/license-info) 約束,這些規定在本文件發布之日生效。請仔細檢閱這些文件,因為它們說明您在本文件方面的權利和限制。從本文件中提取的程式碼元件必須包含「簡化 BSD 授權」文字,如《信託法律規定》第 4.e 節所述,並在沒有擔保的情況下提供,如「簡化 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 中所述。

本文件中使用的術語「JSON」、「JSON 文字」、「JSON 值」、「成員」、「元素」、「物件」、「陣列」、「數字」、「字串」、「布林值」、「true」、「false」和「null」的解釋方式如 RFC 8259 中所定義。

3. 概觀

本文件提出一種新的媒體類型「application/schema+json」,以識別用於描述 JSON 資料的 JSON Schema。它還提出另一種選用的媒體類型「application/schema-instance+json」,以提供額外的整合功能。JSON Schema 本身就是 JSON 文件。本文件和相關規範定義了允許作者以多種方式描述 JSON 資料的關鍵字。

JSON Schema 使用關鍵字來對 JSON 實例聲明限制,或使用額外資訊註釋這些實例。其他關鍵字用於將斷言和註釋應用於更複雜的 JSON 資料結構,或基於某種條件。

為了方便重複使用,關鍵字可以組織成詞彙。詞彙包含關鍵字的清單,以及它們的語法和語義。

JSON Schema 可以透過定義其他詞彙來擴充,或者較不正式地在任何詞彙之外定義其他關鍵字。無法辨識的個別關鍵字會被忽略,而當宣告正在使用哪些詞彙時,可以控制對無法辨識的詞彙的行為。

本文件定義了一個核心詞彙,任何實作都必須支援,並且無法停用。其關鍵字均以「$」字元作為前綴,以強調其必要性。這個詞彙對於「application/schema+json」媒體類型功能的運作至關重要,並且用於引導載入其他詞彙。

此外,本文件定義了一組「建議」的關鍵字詞彙,用於有條件地應用子 schema,以及將子 schema 應用於物件和陣列的內容。無論這些 schema 的目的是用於斷言驗證、註解,或兩者皆是,要為非簡單的 JSON 實例撰寫 schema,都必須使用此詞彙或非常類似的詞彙。雖然它不是必要的核心詞彙的一部分,但為了達到最大的互操作性,本文件仍包含此額外的詞彙,並強烈建議使用。

其他用於結構驗證或超媒體註解等目的的詞彙,則定義在其他文件中。

4. 定義

4.1. JSON 文件

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

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

JSON Schema 僅針對 JSON 文件定義。然而,任何可以解析成或根據 JSON Schema 資料模型處理的文件或記憶體結構,都可以根據 JSON Schema 來解釋,包括像 CBOR 這樣的媒體類型。

4.2. 實例

應用 schema 的 JSON 文件稱為「實例」。

4.2.1. 實例資料模型

JSON Schema 根據資料模型來解釋文件。根據此資料模型解釋的 JSON 值稱為「實例」。

一個實例有六種基本類型之一,並且根據類型有不同的可能值範圍

null
JSON 的「null」產生式
boolean
來自 JSON 的「true」或「false」產生式的「true」或「false」值
object
來自 JSON 的「object」產生式的屬性無序集合,其中屬性將字串映射到一個實例
array
來自 JSON 的「array」產生式的實例有序列表
number
來自 JSON 的「number」產生式的任意精度、以 10 為基底的十進制數值
string
來自 JSON 的「string」產生式的 Unicode 碼點字串

因此,空白和格式化的問題,包括資料模型中相等數值的不同詞彙表示方式,都超出 JSON Schema 的範圍。希望處理詞彙表示方式差異的 JSON Schema 詞彙,應該定義關鍵字來精確解釋資料模型中的格式化字串,而不是依賴於原始 JSON 表示的 Unicode 字元。

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

請注意,JSON Schema 詞彙可以自由定義它們自己的擴展類型系統。這不應與此處定義的核心資料模型類型混淆。例如,「integer」是一種詞彙可以合理定義為關鍵字值的類型,但資料模型不區分整數和其他數字。

4.2.2. 實例媒體類型

JSON Schema 設計為完全適用於 "application/json" 文件,以及使用 "+json" 結構化語法後綴的媒體類型。

某些用於處理 schema 的功能由每個媒體類型定義,即媒體類型參數和 URI 片段識別符號的語法和語義。這些功能分別可用於內容協商和計算實例中特定位置的 URI。

本規範定義 "application/schema-instance+json" 媒體類型,以允許實例作者充分利用參數和片段識別符號來達到這些目的。

4.2.3. 實例相等性

當且僅當兩個 JSON 實例具有相同的類型,並根據資料模型具有相同的值時,才稱它們相等。具體而言,這表示

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

4.3. JSON Schema 文件

JSON Schema 文件,或簡稱 schema,是用於描述實例的 JSON 文件。schema 本身可以解釋為實例,但應始終給予 "application/schema+json" 媒體類型,而不是 "application/schema-instance+json"。"application/schema+json" 媒體類型定義為提供 "application/schema-instance+json" 所提供媒體類型參數和片段識別符號語法和語義的超集。

JSON Schema 必須是一個物件或一個布林值。

4.3.1. JSON Schema 物件和關鍵字

應用於實例的物件屬性稱為關鍵字,或 schema 關鍵字。廣泛來說,關鍵字分為四類:

識別符
透過設定 schema 的標準 URI 和/或變更基本 URI 的決定方式來控制 schema 的識別
斷言
應用於實例時產生布林值結果
註解
將資訊附加到實例以供應用程式使用
應用器
將一個或多個子 schema 應用於實例中的特定位置,並組合或修改其結果
保留位置
不會直接影響結果,而是保留特定用途的位置以確保互操作性

關鍵字可能屬於多個類別,儘管應用器「應該」僅根據其子 schema 的結果產生斷言結果。它們不應定義獨立於其子 schema 的其他約束。

擴展關鍵字,即在本文件及其配套文件之外定義的關鍵字,可以自由定義其他行為。

JSON Schema 可以包含不是 schema 關鍵字的屬性。未知的關鍵字「應該」被忽略。

空 schema 是沒有屬性,或僅有未知屬性的 JSON Schema。

4.3.2. 布林 JSON Schema

布林 schema 值 "true" 和 "false" 是微不足道的 schema,無論實例值為何,它們始終會產生自身作為斷言結果。它們永遠不會產生註解結果。

這些布林 schema 的存在是為了闡明 schema 作者的意圖並促進 schema 處理的優化。它們的行為與以下 schema 物件相同(其中 "not" 是本文件中定義的子 schema 應用詞彙的一部分)。

true
始終通過驗證,就像空 schema {} 一樣
false
始終驗證失敗,就像 schema { "not": {} } 一樣

雖然空 schema 物件是明確的,但 "false" schema 有許多可能的等效項。使用布林值可確保人類讀者和實作都能清楚了解其意圖。

4.3.3. Schema 詞彙

schema 詞彙,或簡稱詞彙,是一組關鍵字、它們的語法和它們的語義。詞彙通常圍繞特定目的組織。JSON Schema 的不同用途,例如驗證、超媒體或使用者介面產生,將涉及不同的詞彙集。

詞彙是 JSON Schema 中重複使用的主要單位,因為 schema 作者可以指示處理 schema 時需要或可選哪些詞彙。由於詞彙在 meta-schema 中由 URI 識別,因此通用實作可以載入擴展以支援先前未知的詞彙。雖然可以在任何詞彙之外支援關鍵字,但沒有類似的機制來指示個別關鍵字的使用。

4.3.4. Meta-Schema

描述 schema 本身的 schema 稱為 meta-schema。Meta-schema 用於驗證 JSON Schema 並指定它們正在使用哪些詞彙。

通常,meta-schema 會指定一組詞彙,並驗證符合這些詞彙語法的 schema。然而,meta-schema 和詞彙是分開的,以便允許 meta-schema 比詞彙的規範要求更嚴格或更寬鬆地驗證 schema 的一致性。Meta-schema 也可能描述並驗證不屬於正式詞彙的其他關鍵字。

4.3.5. 根 Schema 和子 Schema 和資源

JSON Schema 資源是一個 schema,它由 標準 絕對 URI 識別。

根 schema 是包含問題中整個 JSON 文件的 schema。根 schema 始終是一個 schema 資源,其中 URI 的確定方式如第 8.2.1 節所述。

某些關鍵字本身採用 schema,允許 JSON Schema 巢狀結構

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

                        

在此範例文件中,標題為「array item」的 schema 是一個子 schema,而標題為「root」的 schema 是根 schema。

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

如第 8.2.2 節所討論的,JSON Schema 文件可以包含多個 JSON Schema 資源。當不加限定詞使用時,「根 schema」一詞指的是文件的根 schema。在某些情況下,會討論資源根 schema。資源的根 schema 是其頂層 schema 物件,如果資源被提取到獨立的 JSON Schema 文件中,它也將是文件根 schema。

5. 片段識別符號

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

此外,"application/schema+json" 媒體類型支援兩種片段識別符號結構:純名稱和 JSON 指標。"application/schema-instance+json" 媒體類型支援一種片段識別符號結構:JSON 指標。

JSON 指標作為 URI 片段識別符號的使用在 RFC 6901 中描述。對於支援兩種片段識別符號語法的 "application/schema+json",與 JSON 指標語法匹配的片段識別符號(包括空字串)「必須」解釋為 JSON 指標片段識別符號。

根據 W3C 的片段識別碼最佳實務,"application/schema+json" 中的純名稱片段識別碼保留給參照本地命名的 schema。所有不符合 JSON 指標語法的片段識別碼,都必須被解釋為純名稱片段識別碼。

在 "application/schema+json" 文件中定義和參照純名稱片段識別碼,已在"$anchor" 關鍵字章節中指定。

6. 一般考量

6.1. JSON 值的範圍

實例可以是任何有效的 JSON 值,如JSON所定義。JSON Schema 不對類型施加任何限制:JSON Schema 可以描述任何 JSON 值,包括例如 null。

6.2. 程式語言獨立性

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

6.3. 數學整數

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

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

6.4. 正規表示式

關鍵字「可以」使用正規表示式來表達約束,或將實例值約束為正規表示式。這些正規表示式「應該」根據ECMA 262, 第 15.10.1 節中描述的正規表示式方言有效。

此外,鑑於正規表示式建構支援方面存在很大差異,schema 作者「應該」將自己限制在以下正規表示式符記:

最後,實作「不得」將正規表示式視為錨定,無論是開頭還是結尾。這表示,例如,模式 "es" 符合 "expression"。

6.5. 擴展 JSON Schema

其他 schema 關鍵字和 schema 詞彙「可以」由任何實體定義。除了明確的協議外,schema 作者「不應」期望這些額外的關鍵字和詞彙受到未明確記錄此類支援的實作的支援。實作「應該」忽略它們不支援的關鍵字。

實作「可以」提供註冊或載入它們不直接支援的詞彙處理程式的能力。註冊和實作此類處理程式的確切機制取決於實作方式。

7. 關鍵字行為

JSON Schema 關鍵字分為幾個一般行為類別。斷言驗證實例是否滿足約束,產生布林值結果。註釋附加應用程式可以以任何他們認為合適的方式使用的資訊。應用器將子 schema 應用於實例的部分,並組合其結果。

擴展關鍵字「應該」保留在這些類別中,請記住,特別是註釋非常靈活。複雜的行為通常最好基於註釋資料委派給應用程式,而不是直接作為 schema 關鍵字實作。但是,擴展關鍵字「可以」為特殊目的定義其他行為。

針對 schema 評估實例涉及針對實例內適當位置處理 schema 中的所有關鍵字。通常,會處理應用器關鍵字,直到到達沒有應用器(因此也沒有子 schema)的 schema 物件。實例中的適當位置會針對 schema 物件中的斷言和註釋關鍵字進行評估,其結果會根據應用器的規則收集到父 schema 中。

一旦其所有子 schema 都經過評估,父 schema 物件的評估就可以完成,儘管在某些情況下,由於斷言結果,評估可能會短路。當收集註釋時,某些斷言結果短路是不可能的,因為需要檢查所有子 schema 以進行註釋收集,包括那些無法進一步改變斷言結果的子 schema。

7.1. 語彙範圍和動態範圍

雖然大多數 JSON Schema 關鍵字可以自行評估,或者最多只需要考慮同一 schema 物件中相鄰關鍵字的值或結果,但少數關鍵字具有更複雜的行為。

關鍵字的語彙範圍由物件和陣列的巢狀 JSON 資料結構決定。最大的範圍是整個 schema 文件。最小的範圍是沒有子 schema 的單個 schema 物件。

關鍵字「可以」定義為部分值,例如 URI 參考,必須針對另一個值(例如另一個 URI 參考或完整 URI)進行解析,該值是透過 JSON 文件的語彙結構找到的。"$id" 核心關鍵字和 "base" JSON 超 schema 關鍵字是此類行為的範例。此外,此規格中的 "$ref" 和 "$recursiveRef" 以這種方式解析其值,儘管它們不會變更如何解析進一步的值。

請注意,某些關鍵字(例如 "$schema")適用於整個 schema 文件的語彙範圍,因此「必須」僅出現在 schema 資源的根 schema 中。

其他關鍵字可能會考慮 schema 評估期間存在的動態範圍,通常與實例文件一起。最外層的動態範圍是開始處理的 schema 文件之根 schema。從此根 schema 到任何特定關鍵字的路徑(包括可能已解析的任何 "$ref" 和 "$recursiveRef" 關鍵字)被視為關鍵字的「驗證路徑」。[CREF1]或者這應該是開始處理的 schema 物件,即使它不是根?這對於僅允許在根 schema 中使用 "$recursiveAnchor" 但處理在子 schema 中開始的情況有一些影響。

語彙和動態範圍對齊,直到遇到參考關鍵字。當遵循參考關鍵字將處理從一個語彙範圍移到另一個語彙範圍時,從動態範圍的角度來看,遵循參考與下降到以值形式存在的子 schema 沒有什麼不同。該參考遠端的關鍵字透過動態範圍解析資訊時,會將參考的起始端視為其動態父項,而不是檢查本地語彙上封閉的父項。

動態範圍的概念主要與 "$recursiveRef" 和 "$recursiveAnchor" 一起使用,應被視為進階功能,並且在定義其他關鍵字時應謹慎使用。它也會在報告錯誤和收集的註釋時出現,因為有可能使用不同的動態範圍重複訪問相同的語彙範圍。在這種情況下,務必通知使用者產生錯誤或註釋的動態路徑。

7.2. 關鍵字互動

關鍵字行為「可以」根據子 schema和/或相鄰關鍵字的註釋結果定義。此類關鍵字「不得」導致循環相依性。關鍵字「可以」根據同一schema 物件中是否存在其他關鍵字來修改其行為。

7.3. 預設行為

遺失的關鍵字「不得」產生錯誤的斷言結果,「不得」產生註釋結果,且「不得」導致任何其他 schema 作為其自身行為定義的一部分進行評估。但是,鑑於遺失的關鍵字不貢獻註釋,缺少註釋結果可能會間接變更其他關鍵字的行為。

在某些情況下,關鍵字的遺失關鍵字斷言行為與特定值產生的行為相同,關鍵字定義「應該」在已知的情況下記錄此類值。但是,即使產生預設行為的值在存在時會產生註釋結果,預設行為仍然「不得」產生註釋。

由於註釋收集在計算和記憶體方面都會增加大量成本,因此實作「可以」選擇退出此功能。已知實作具有取決於註釋結果的斷言或應用器行為的關鍵字「必須」被視為錯誤,除非可以使用產生相同行為的替代實作。此類關鍵字「應該」在適當時描述合理的替代方法。本文檔中的 "additionalItems" 和 "additionalProperties" 關鍵字說明了此方法。

7.4. 識別碼

識別碼設定 schema 的標準 URI,或影響此類 URI 在參考中的解析方式,或兩者皆是。本文檔中定義的核心詞彙定義了多個識別關鍵字,最顯著的是 "$id"。

標準 schema URI 在處理實例時「不得」變更,但影響 URI 參考解析的關鍵字「可以」具有僅在執行階段完全確定的行為。

雖然可以自訂識別碼關鍵字,但詞彙設計者應注意不要破壞核心關鍵字的運作。例如,此規格中的 "$recursiveAnchor" 關鍵字將其 URI 解析效果限制為相符的 "$recursiveRef" 關鍵字,而不會影響 "$ref"。

7.5. 應用器

應用器允許建構比單個 schema 物件所能完成的更複雜的 schema。針對schema 文件評估實例,首先將根 schema應用於完整的實例文件。從那裡開始,使用稱為應用器的關鍵字來確定要應用哪些其他 schema。此類 schema 可以就地應用於目前位置,或應用於子位置。

要應用的 schema 可以作為構成關鍵字值全部或一部分的子 schema 存在。或者,應用器可以參考同一 schema 文件中或其他 schema 文件中的 schema。識別此類參考 schema 的機制由關鍵字定義。

應用器關鍵字也定義了子模式或參照模式的布林斷言結果如何被修改和/或組合,以產生應用器的布林結果。應用器可以對子模式的斷言結果應用任何布林邏輯運算,但**不得**引入自身新的斷言條件。

註解結果會根據每個註解關鍵字指定的規則進行組合。

7.5.1. 參照和參考模式

第 7.5 節所述,應用器關鍵字可能會參照要應用的模式,而不是將其作為子模式包含在應用器的值中。在這種情況下,被應用的模式稱為參照模式,而包含應用器關鍵字的模式稱為參考模式。

雖然根模式和子模式是基於模式在模式文件中的位置的靜態概念,但參照和參考模式是動態的。在針對模式評估實例期間,不同的模式對可能會發現自己處於各種參照和參考安排中。

對於某些按引用應用的應用器,例如 "$ref",可以透過對模式文件詞彙範圍的靜態分析來確定參照模式。其他應用器,例如 "$recursiveRef" 和 "$recursiveAnchor",可能會使用動態範圍,因此只能在評估實例模式的過程中解析。

7.6. 斷言

JSON Schema 可用於對 JSON 文件斷言約束,該文件會通過或未能通過斷言。此方法可用於驗證是否符合約束,或記錄滿足約束的必要條件。

當針對模式斷言評估實例時,JSON Schema 實作會產生單一的布林結果。

實例只能未能通過模式中存在的斷言。

7.6.1. 斷言與實例基本類型

大多數斷言只約束特定基本類型中的值。當實例的類型不是關鍵字針對的類型時,則認為實例符合斷言。

例如,配套的驗證詞彙表中的 "maxLength" 關鍵字:只會限制某些(過長的)字串為無效。如果實例是數字、布林值、空值、陣列或物件,則它對於此斷言而言是有效的。

此行為允許關鍵字更容易地與可以是多個基本類型的實例一起使用。配套的驗證詞彙表還包括一個 "type" 關鍵字,它可以獨立地將實例限制為一個或多個基本類型。這允許簡潔地表達諸如可能返回特定長度的字串或空值的函數的用例。

{
    "type": ["string", "null"],
    "maxLength": 255
}

                        

如果 "maxLength" 也將實例類型限制為字串,那麼這會更難以表達,因為編寫的範例實際上不允許空值。除非另有明確指定,否則每個關鍵字都會單獨評估,因此如果 "maxLength" 將實例限制為字串,那麼在 "type" 中包含 "null" 將不會有任何有效的作用。

7.7. 註解

每當實例針對包含註解的模式物件及其所有父模式物件進行驗證時,JSON Schema 都可以使用資訊註解實例。該資訊可以是簡單的值,也可以根據實例內容計算得出。

註解會附加到實例中的特定位置。由於許多子模式都可以應用於任何單一位置,因此註解關鍵字需要指定對具有不同值的多個適用的關鍵字出現的任何不尋常處理方式。

與斷言結果不同,註解資料可以採用多種形式,並提供給應用程式以供其自行決定使用。JSON Schema 實作不應代表應用程式使用收集的資訊。

除非另有規定,否則註解關鍵字的註解值就是關鍵字的值。但是,也可能出現其他行為。例如,JSON Hyper-Schema 的 "links" 關鍵字是一種複雜的註解,它會產生一個部分基於實例資料的值。

雖然斷言可以進行「短路」評估,但收集註解需要檢查適用於實例位置的所有模式,即使它們無法變更整體的斷言結果。唯一的例外是,未能通過驗證的模式物件的子模式可能會被跳過,因為不會保留失敗模式的註解。

7.7.1. 收集註解

註解由明確定義註解收集行為的關鍵字收集。請注意,布林模式無法產生註解,因為它們不使用關鍵字。

收集的註解**必須**包含以下資訊

如果同一個關鍵字將來自多個模式位置的值附加到同一個實例位置,並且註解定義了組合這些值的過程,則組合值也**必須**與實例位置相關聯。本規範中描述的輸出格式(包含註解資訊)符合此要求。

7.7.1.1. 區分多個值

應用程式**可以**根據提供值的模式位置,決定使用多個註解值中的哪一個。這樣做的目的是為了允許彈性的使用。收集模式位置有助於此類使用。

例如,考慮以下模式,該模式使用來自驗證規範的註解和斷言

請注意,為了清楚起見,某些行會換行。

{
    "title": "Feature list",
    "type": "array",
    "items": [
        {
            "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 將使用該描述,並附加其本地定義的描述,以解釋如何解釋空值。

請注意,其他應用程式可能會採用其他合理的方法。例如,應用程式可能會認為存在兩個不同的 "default" 值是一種錯誤,無論其模式位置如何。

7.7.1.2. 註解和斷言

產生 false 斷言結果的模式物件**不得**產生任何註解結果,無論是來自其自身的關鍵字,還是來自子模式中的關鍵字。

請注意,整體模式結果可能仍然包含從其他模式位置收集的註解。考慮以下模式

{
    "oneOf": [
        {
            "title": "Integer Value",
            "type": "integer"
        },
        {
            "title": "String Value",
            "type": "string"
        }
    ]
}

                            

和實例 "This is a string",標題註解 "Integer Value" 會被捨棄,因為該模式物件中的類型斷言失敗。標題註解 "String Value" 會保留,因為實例通過了字串類型斷言。

7.7.1.3. 註解和應用器

除了可能定義自己的註解結果外,應用器關鍵字還會彙總在其子模式或參照模式中收集的註解。彙總註解值的規則由每個註解關鍵字定義,並且不受用於組合斷言結果的邏輯的直接影響。

7.8. 保留位置

第四類關鍵字只是保留一個位置,以容納可重複使用的元件或模式作者感興趣的資料,這些資料不適合重複使用。這些關鍵字不會影響驗證或註解結果。它們在核心詞彙表中的目的是確保位置可用於某些目的,並且不會被延伸關鍵字重新定義。

雖然這些關鍵字不會直接影響結果,但如8.2.4.4 節中所述,未識別的延伸關鍵字(為可重複使用模式保留位置)在某些情況下可能會與參考產生不良的互動。

8. JSON Schema 核心詞彙表

本節中宣告的所有以 "$" 開頭的關鍵字,構成了 JSON Schema 核心詞彙表。這些關鍵字是處理任何模式或中繼模式(包括那些跨多個文件分割的模式)所必需的,或者它們的存在是為了保留關鍵字以供需要保證互操作性的用途。

為了引導進一步詞彙表的處理,核心詞彙表**必須**始終被視為強制性的。使用 "$vocabulary" 關鍵字來宣告所使用詞彙表的中繼模式,**必須**明確列出核心詞彙表,其值**必須**為 true,表示它是必需的。

此詞彙表(且僅限此詞彙表)的 false 值行為是未定義的,當 "$vocabulary" 存在但未包含核心詞彙表時的行為也是未定義的。但是,建議實作偵測這些情況,並在發生這些情況時引發錯誤。宣告中繼模式選擇性使用 Core 沒有任何意義。

不使用 "$vocabulary" 的中繼模式**必須**被認為需要核心詞彙表,如同其 URI 存在且值為 true 一樣。

核心詞彙表目前的 URI 為:<https://json-schema.dev.org.tw/draft/2019-09/vocab/core>

相應的中繼模式目前的 URI 為:<https://json-schema.dev.org.tw/draft/2019-09/meta/core>

雖然 "$" 字首並未正式保留給核心詞彙表,但建議延伸關鍵字(在詞彙表中或其他情況下)以非 "$" 字元開頭,以避免未來可能發生衝突。

8.1. 中繼模式和詞彙表

中繼模式和詞彙表這兩個概念用於告知實作如何解釋模式。每個模式都有一個中繼模式,可以使用 "$schema" 關鍵字宣告。

中繼模式有兩個用途

宣告所使用的詞彙表
當 "$vocabulary" 關鍵字出現在中繼模式中時,它會宣告哪些詞彙表可用於參考該中繼模式的模式中。詞彙表定義關鍵字語意以及它們的一般語法。
描述有效的模式語法
模式**必須**成功針對其相容的中繼模式進行驗證,該中繼模式會限制可用關鍵字的語法。描述的語法預期與宣告的詞彙表相容;雖然可以描述不相容的語法,但這樣的中繼模式不太可能有用。

中繼綱要(Meta-schema)與詞彙表(vocabularies)是分開的,這樣可以讓詞彙表以不同的方式組合,並讓中繼綱要的作者可以施加額外的約束,例如禁止某些關鍵字,或執行異常嚴格的語法驗證,這可能在開發和測試週期中進行。每個詞彙表通常會識別一個僅包含該詞彙表關鍵字的中繼綱要。

中繼綱要的編寫是 JSON 綱要的高階應用,因此中繼綱要功能的設計強調彈性而非簡單性。

8.1.1.「$schema」關鍵字

「$schema」關鍵字既用作 JSON 綱要功能集的識別符,也用作資源的識別符,該資源本身是一個 JSON 綱要,描述了為此特定功能集編寫的有效綱要集。

此關鍵字的值必須是 URI (包含 scheme),且此 URI 必須被正規化。目前的綱要必須符合此 URI 所識別的中繼綱要。

如果此 URI 識別的是可檢索的資源,則該資源的媒體類型應為 "application/schema+json"。

「$schema」關鍵字應在資源的根綱要中使用。它不得出現在資源的子綱要中。如果根綱要中缺少此關鍵字,則產生的行為是實現定義的。

如果單一文件中存在多個綱要資源,則所有綱要資源的「$schema」值應相同。在同一個綱要文件中,「$schema」值不同的結果是實現定義的。[CREF2]在同一個文件中使用多個「$schema」關鍵字會暗示功能集和因此的行為可以在文件中變更。這會導致需要解決許多尚未明確定義的實現問題。因此,雖然僅在根綱要中使用「$schema」的模式可能仍然是綱要編寫的最佳實踐,但實現行為可能會在未來草案中進行修訂或放寬。 [CREF3]為嵌入式綱要資源所做的例外,是為了允許將多個綱要資源捆綁到單一綱要文件中,而無需變更其內容,如本規範稍後所述。

此屬性的值在本文檔和其他文件中,以及其他方定義。

8.1.2.「$vocabulary」關鍵字

「$vocabulary」關鍵字用於中繼綱要中,以識別在該中繼綱要所描述的綱要中可用的詞彙表。它也用於指示每個詞彙表是必要還是可選的,其意義在於,實現必須理解必要的詞彙表才能成功處理綱要。

此關鍵字的值必須是一個物件。物件中的屬性名稱必須是 URI (包含 scheme),且此 URI 必須被正規化。每個作為屬性名稱出現的 URI 都識別一組特定的關鍵字及其語意。

URI 可以是 URL,但可檢索資源的性質目前未定義,並保留供將來使用。詞彙表作者可以使用詞彙表規範的 URL,以人類可讀的媒體類型(例如 text/html 或 text/plain)作為詞彙表 URI。[CREF4]詞彙表文件可能會在即將推出的草案中添加。目前,識別關鍵字集被認為是足夠的,因為這與中繼綱要驗證一起,是目前「詞彙表」的工作方式。任何未來的詞彙表文件格式都將指定為 JSON 文件,因此在此期間使用 text/html 或其他非 JSON 格式不會產生任何未來的歧義。

物件屬性的值必須是布林值。如果值為 true,則不識別詞彙表的實現必須拒絕處理任何使用「$schema」宣告此中繼綱要的綱要。如果值為 false,則不識別詞彙表的實現應繼續處理此類綱要。

根據 6.5,無法識別的關鍵字應被忽略。這對於無法識別詞彙表定義的關鍵字仍然適用。目前無法區分無法識別的關鍵字是否在詞彙表中定義,還是不屬於任何詞彙表。

「$vocabulary」關鍵字應在任何預期用作中繼綱要的綱要文件的根綱要中使用。它不得出現在子綱要中。

在未作為中繼綱要處理的綱要文件中,「$vocabulary」關鍵字必須被忽略。這允許驗證中繼綱要 M 對其自身的中繼綱要 M',而無需驗證器理解 M 所宣告的詞彙表。

8.1.2.1. 預設詞彙表

如果缺少「$vocabulary」,實現可以根據中繼綱要來決定行為,如果中繼綱要是從引用綱要的「$schema」關鍵字的 URI 值中識別出來的。這是先前在詞彙表存在之前如何識別行為(例如 Hyper-Schema 用法)的方式。

如果綱要所引用的中繼綱要無法識別或遺失,則行為是實現定義的。如果實現繼續處理綱要,它必須假定使用核心詞彙表。如果實現是為特定目的而建立的,則它應假定使用最相關的所有詞彙表。

例如,驗證器實現應假定使用本規範及其配套的驗證規範中的所有詞彙表。

8.1.2.2. 詞彙表的不可繼承性

請注意,「$vocabulary」的處理限制意味著使用「$ref」或類似關鍵字引用其他中繼綱要的中繼綱要,不會自動繼承其他中繼綱要的詞彙表宣告。所有此類宣告都必須在每個預期用作中繼綱要的綱要文件的根目錄中重複。這在 中繼綱要範例中示範。[CREF5]此要求允許實現在每個中繼綱要的單一位置中找到所有詞彙表需求資訊。由於綱要可擴展性意味著可以透過參照來組合更精細的中繼綱要有無數種潛在方法,因此要求實現在參照的中繼綱要中預期所有可能性並搜尋詞彙表將會過於繁瑣。

8.1.3. 中繼綱要和詞彙表 URI 的更新

詞彙表和中繼綱要 URI 的更新可能會在規範草案之間發佈,以更正錯誤。實現應考慮本規範草案之後和下一個規範草案之前的日期 URI,以表示與此處列出的語法和語意相同。

8.1.4. 偵測中繼綱要

如果綱要是因為被另一個綱要的「$schema」關鍵字識別為中繼綱要而進行檢查,則實現必須將該綱要識別為中繼綱要。這意味著單一綱要文件有時可能會被視為一般綱要,而有時會被視為中繼綱要。

在檢查一個綱要,該綱要本身是自己的中繼綱要的情況下,當實現開始將其作為一般綱要處理時,它會根據這些規則進行處理。但是,當由於檢查其自身的「$schema」值而第二次載入時,它會被視為中繼綱要。因此,同一個文件會在一個會期中以兩種方式進行處理。

實現可以允許明確將綱要作為中繼綱要傳遞,用於實現特定的目的,例如預先載入常用的中繼綱要並預先檢查其詞彙表支援需求。中繼綱要作者不得期望此類功能可以在不同的實現之間互通。

8.2. 基礎 URI、錨點和取消參考

為了區分龐大生態系統中的綱要,綱要是透過 URI 來識別的,並且可以透過指定其 URI 來嵌入對其他綱要的引用。

有幾個關鍵字可以接受相對 URI-參考,或用於建構相對 URI-參考的值。對於這些關鍵字,有必要建立基礎 URI 以解析參考。

8.2.1. 初始基礎 URI

RFC3986 第 5.1 節定義如何決定文件的預設基礎 URI。

作為參考資訊,綱要的初始基礎 URI 是找到該綱要的 URI,無論是網路位置、本機檔案系統,還是任何其他可透過任何已知 scheme 的 URI 識別的情況。

如果綱要文件未使用「$id」定義任何明確的基礎 URI(嵌入在內容中),則基礎 URI 是根據 RFC 3986 第 5 節決定的。

如果沒有已知來源,或者來源沒有已知的 URI scheme,則可以使用適當的特定實現的預設 URI,如 RFC 3986 第 5.1.4 節所述。建議實現記錄它們假設的任何預設基礎 URI。

除非根綱要中存在下一節中描述的「$id」關鍵字,否則此基礎 URI 應被視為綱要文件根綱要資源的標準 URI。

8.2.2. 「$id」關鍵字

「$id」關鍵字使用其標準 URI 來識別綱要資源。

請注意,此 URI 是一個識別符,不一定是網路定位器。如果是網路可定址的 URL,則綱要不必能從其標準 URI 下載。

如果存在,此關鍵字的值必須是字串,且必須表示有效的 URI-參考。此 URI-參考應被正規化,且必須解析為 絕對 URI (沒有片段)。因此,「$id」不得包含非空的片段,並且不應包含空的片段。

由於應用程式/綱要+json 媒體類型的上下文中,空的片段與沒有片段的基礎 URI 指的是相同的資源,因此實現可以透過移除片段來正規化以空的片段結尾的 URI。但是,綱要作者不應依賴跨實現的此行為。[CREF6]主要允許這樣做是因為較舊的中繼綱要在其 $id(或之前的 id)中有空的片段。未來的草案可能會完全禁止在「$id」中出現空的片段。

根據 RFC 3986 第 5.1.1 節關於嵌入在內容中的基礎 URI,此 URI 也作為綱要資源內關鍵字中相對 URI 參考的基礎 URI。

子模式中若存在「$id」,表示該子模式在單一 schema 文件內構成一個獨立的 schema 資源。此外,根據RFC 3986 第 5.1.2 節關於封裝實體的規定,若子模式中的「$id」是一個相對 URI 參考,則解析該參考的基準 URI 為父 schema 資源的 URI。

如果沒有父 schema 物件明確使用「$id」將自身識別為資源,則基準 URI 為整個文件的 URI,如同前一節中給定的步驟所建立的。

8.2.2.1. 識別根 schema

JSON Schema 文件的根 schema 應包含一個具有絕對 URI(包含 scheme,但不包含片段)的「$id」關鍵字。

8.2.2.2. JSON 指標片段與嵌入式 schema 資源

由於 JSON 指標 URI 片段是根據 schema 文件的結構建構而成,嵌入式 schema 資源及其子模式可透過相對於自身規範 URI,或相對於包含資源 URI 的 JSON 指標片段來識別。

從概念上講,一組連結的 schema 資源的行為應完全相同,無論每個資源是使用schema 參考連接的獨立文件,還是結構化為單一文件,其中一個或多個 schema 資源以子模式形式嵌入。

由於涉及相對於父 schema 資源 URI 的 JSON 指標片段的 URI,當嵌入式 schema 被移動到單獨的文件並被參考時,這些 URI 將不再有效,因此應用程式和 schema 不應使用此類 URI 來識別嵌入式 schema 資源或其中的位置。

考慮以下包含另一個嵌入其中的 schema 資源的 schema 文件

{
  "$id": "https://example.com/foo",
  "items": {
    "$id": "https://example.com/bar",
    "additionalProperties": { }
  }
}

                            

URI 「https://example.com/foo#/items/additionalProperties」指向嵌入資源中「additionalProperties」關鍵字的 schema。然而,該 schema 的規範 URI 為「https://example.com/bar#/additionalProperties」。

現在考慮以下兩個透過「$ref」的 URI 值以參考方式連結的 schema 資源

{
  "$id": "https://example.com/foo",
  "items": {
    "$ref": "bar"
  }
}

{
  "$id": "https://example.com/bar",
  "additionalProperties": { }
}

                            

在這裡,我們看到該「additionalProperties」子模式的規範 URI 仍然有效,而以「#/items/$ref」開頭的非規範 URI 現在解析為無。

另請注意,「https://example.com/foo#/items」在這兩種安排中都有效,但會解析為不同的值。此 URI 的功能類似於資源的檢索 URI。雖然有效,但檢查解析值並使用「$id」(如果值是子模式),或解析參考並使用參考目標的「$id」會更好。

實作可以選擇不支援透過非規範 URI 尋址 schema。因此,建議 schema 作者僅使用規範 URI,因為使用非規範 URI 可能會降低 schema 的互通性。[CREF7]這是為了避免要求實作追蹤每個可能的基準 URI 和 JSON 指標片段的整個堆疊,因為如果 schema 資源被重組,除了其中一個以外,其他都會變得脆弱。有些人認為這很容易,因此沒有必要禁止它,而另一些人則認為這會使 schema 識別變得複雜,因此應該禁止。我們鼓勵對此議題提供回饋意見。

附錄 A 中提供了此類非規範 URI 的更多範例,以及應使用的適當規範 URI。

8.2.3. 使用「$anchor」定義與位置無關的識別符號

使用 JSON 指標片段需要了解 schema 的結構。當編寫 schema 文件旨在提供可重複使用的 schema 時,最好使用未與任何特定結構位置綁定的純名稱片段。這允許重新定位子模式,而無需更新 JSON 指標參考。

「$anchor」關鍵字用於指定此類片段。它是一個識別符號關鍵字,只能用於建立純名稱片段。

如果存在,此關鍵字的值必須為字串,且必須以字母 ([A-Za-z]) 開頭,後跟任意數量的字母、數字 ([0-9])、連字號 ("-")、底線 ("_")、冒號 (":") 或句點 (".")。[CREF8]請注意,錨點字串不包含 "#" 字元,因為它不是 URI 參考。「$anchor": "foo" 在 URI 中使用時會變成片段「#foo」。有關完整範例,請參閱下文。

附加結果片段的基準 URI 由「$id」關鍵字確定,如上一節所述。如果兩個「$anchor」關鍵字適用於不同的基準 URI,則它們在同一 schema 文件中可以具有相同的值,因為產生的完整 URI 將會不同。但是,兩個具有相同值和相同基準 URI 的「$anchor」關鍵字的效果是未定義的。如果偵測到此類用法,實作可能會引發錯誤。

8.2.4. Schema 參考

多個關鍵字可用於參考將應用於當前實例位置的 schema。「$ref」和「$recursiveRef」是應用程式關鍵字,將參考的 schema 應用於實例。「$recursiveAnchor」是一個識別符號關鍵字,用於控制如何確定解析「$recursiveRef」的 URI 參考值的基準 URI。

由於「$ref」和「$recursiveRef」的值是 URI 參考,這使得可以將 schema 外部化或分散到多個文件中,並提供透過自我參考驗證遞迴結構的能力。

這些關鍵字產生的解析 URI 不一定是網路定位器,而僅是識別符號。如果 schema 是可透過網路尋址的 URL,則不必從該位址下載,並且實作不應假設在遇到可透過網路尋址的 URI 時應執行網路操作。

8.2.4.1. 使用「$ref」進行直接參考

「$ref」關鍵字是一個應用程式,用於參考靜態識別的 schema。其結果是參考 schema 的結果。[CREF9]請注意,此定義決定了結果如何,這表示其他關鍵字可以與「$ref」一起出現在同一個 schema 物件中。

「$ref」屬性的值必須是一個字串,該字串是 URI 參考。相對於當前 URI 基準進行解析,它會產生要應用的 schema 的 URI。

8.2.4.2. 使用「$recursiveRef」和「$recursiveAnchor」進行遞迴參考

「$recursiveRef」和「$recursiveAnchor」關鍵字用於建構可擴充的遞迴 schema。遞迴 schema 是指具有對自身根目錄的參考(透過空片段 URI 參考(「#」)識別)的 schema。

簡單來說,「$recursiveRef」的行為與「$ref」相同,除非其目標 schema 包含值為 true 的「$recursiveAnchor」。在這種情況下,會檢查動態範圍以確定新的基準 URI,「$recursiveRef」中的 URI 參考會根據該基準 URI 重新評估。與使用「$id」變更基準 URI 不同,使用「$recursiveAnchor」的變更是每次解析「$recursiveRef」時計算的,並且不會影響任何其他關鍵字。

有關使用這些關鍵字的範例,請參閱附錄 C[CREF10]先前草案中的超 schema 元 schema 與此草案之間的差異顯著地展示了這些關鍵字的實用性。

8.2.4.2.1. 使用「$recursiveRef」進行動態遞迴參考

「$recursiveRef」屬性的值必須是一個字串,該字串是 URI 參考。它是一個按參考方式的應用程式,它使用動態計算的基準 URI 來解析其值。

此關鍵字的行為僅針對值「#」定義。實作可以選擇將其他值視為錯誤。[CREF11]此限制在未來可能會放寬,但迄今為止,只有值「#」有明確的用例。

「$recursiveRef」的值最初會根據當前基準 URI 進行解析,其方式與「$ref」相同。

檢查由結果 URI 識別的 schema 中是否存在「$recursiveAnchor」,並計算新的基準 URI,如以下章節中針對該關鍵字所述。

最後,「$recursiveRef」的值會根據根據「$recursiveAnchor」確定的新基準 URI 進行解析,產生最終的解析參考 URI。

請注意,在沒有「$recursiveAnchor」的情況下(以及在某些情況下存在時),「$recursiveRef」的行為與「$ref」的行為相同。

與「$ref」一樣,此關鍵字的結果是參考 schema 的結果。

8.2.4.2.2. 使用「$recursiveAnchor」啟用遞迴

「$recursiveAnchor」屬性的值必須是布林值。

「$recursiveAnchor」用於在執行時動態識別「$recursiveRef」的基準 URI,方法是標記可以開始計算的位置和停止計算的位置。此關鍵字不得影響其他關鍵字的基準 URI,除非它們被明確定義為依賴它。

如果設定為 true,則當包含的 schema 物件用作「$recursiveRef」的目標時,會透過檢查動態範圍來確定新的基準 URI,以尋找也包含值為 true 的「$recursiveAnchor」的最外層 schema。然後,該 schema 的基準 URI 會用作動態基準 URI。

如果不存在此類 schema,則基準 URI 不會變更。

如果此關鍵字設定為 false,則基準 URI 不會變更。

省略此關鍵字的行為與值為 false 的行為相同。

8.2.4.3. 防止無限遞迴

schema 不得針對實例運行進入無限循環。例如,如果兩個 schema 「#alice」和「#bob」都具有一個指向另一個的「allOf」屬性,則一個天真的驗證器可能會陷入無限的遞迴循環中,試圖驗證實例。Schema 不應使用此類無限遞迴巢狀結構;該行為是未定義的。

8.2.4.4. 參考可能的非 Schema

子 schema 物件(或布林值)透過它們與已知的應用程式關鍵字或位置保留關鍵字(例如,將一個或多個子 schema 作為值的「$defs」)一起使用來識別。這些關鍵字可以是「$defs」和本文檔中的標準應用程式,或來自已知詞彙表的擴充關鍵字,或實作特定的自訂關鍵字。

多層結構的未知關鍵字能夠引入巢狀子模式,這些子模式將受限於 "$id" 的處理規則。因此,在這種無法識別的結構中擁有參考目標無法可靠地實現,且結果行為是未定義的。同樣地,在已知關鍵字下,其值已知不是模式的參考目標,也會導致未定義的行為,以避免實作需要偵測此類目標。 [CREF12]這些情況類似於透過 HTTP 取得模式,但收到 Content-Type 不是 application/schema+json 的回應。實作當然可以嘗試將其解釋為模式,但原始伺服器沒有保證它實際上是任何此類東西。因此,將其解釋為模式具有安全性隱含意義,並可能產生不可預測的結果。

請注意,與 "$defs" 具有相同語法和語義的單層自訂關鍵字不允許任何介入的 "$id" 關鍵字,因此在嘗試使用任何參考目標作為模式的實作下將會正確運作。然而,此行為是實作特定的,且絕不能為了互通性而依賴它。

8.2.4.5. 載入被參考的模式

使用 URI 來識別遠端模式並不一定意味著會下載任何東西,而是 JSON Schema 實作應該預先了解它們將會使用哪些模式,以及識別它們的 URI。

當下載模式時,例如由在執行時才知道要下載哪些模式的通用使用者代理程式下載時,請參閱 超媒體的用法

實作應該能夠將任意 URI 與任意模式相關聯,和/或自動關聯模式的 "$id" 給定的 URI,具體取決於驗證器對模式的信任程度。此類 URI 和模式可以在處理實例之前提供給實作,或者可以在處理模式文件時記錄下來,產生如附錄 A 所示的關聯。

一個模式可能(而且很可能)有多個 URI,但一個 URI 無法識別多個模式。當多個模式嘗試識別為相同的 URI 時,驗證器應該引發錯誤條件。

8.2.4.6. 取消參考

模式可以由任何已給定它們的 URI 識別,包括 JSON 指標或它們直接由 "$id" 給定的 URI。在所有情況下,取消參考 "$ref" 參考都涉及首先根據 RFC 3986 將其值解析為相對於目前基礎 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> 模式時,它會將 "$id" URI 參考解析為相對於目前基礎 URI 的 <https://example.net/root.json#item>。

當實作接著查看 <#/items> 模式內部時,它會遇到 <#item> 參考,並將其解析為 <https://example.net/root.json#item>,它已在這個相同文件中看到定義,因此可以自動使用。

當實作遇到對 "other.json" 的參考時,它會將其解析為 <https://example.net/other.json>,這未在此文件中定義。如果已將具有該識別碼的模式提供給實作,它也可以自動使用。 [CREF13]當參考的模式未知時,實作應該怎麼做?在哪些情況下允許自動網路取消參考?同源政策?使用者可配置的選項?在由超模式描述的不斷演進的 API 的情況下,預期新的模式將會動態地新增到系統中,因此強加預先載入模式文件的絕對要求是不可行的。

8.2.5. 使用 "$defs" 重複使用模式

"$defs" 關鍵字保留了一個位置,供模式作者將可重複使用的 JSON Schema 內嵌到更通用的模式中。此關鍵字不會直接影響驗證結果。

此關鍵字的值必須是一個物件。此物件的每個成員值都必須是有效的 JSON Schema。

{
    "type": "array",
    "items": { "$ref": "#/$defs/positiveInteger" },
    "$defs": {
        "positiveInteger": {
            "type": "integer",
            "exclusiveMinimum": 0
        }
    }
}

                            

例如,這是一個描述正整數陣列的模式,其中正整數約束是 "$defs" 中的子模式

8.3. 使用 "$comment" 進行註解

此關鍵字保留一個位置,供模式作者向模式的讀者或維護者提供註解。

此關鍵字的值必須是一個字串。實作絕不能將此字串呈現給終端使用者。用於編輯模式的工具應該支援顯示和編輯此關鍵字。此關鍵字的值可以用於除錯或錯誤輸出,這些輸出旨在供開發人員使用模式。

模式詞彙表應該允許在任何包含詞彙表關鍵字的物件中使用 "$comment"。實作可以假設允許 "$comment",除非詞彙表明確禁止。詞彙表絕不能指定除本規範中描述的以外的任何 "$comment" 效果。

將其他媒體類型或程式語言翻譯為 application/schema+json 以及從其翻譯而來的工具,可以選擇將該媒體類型或程式語言的原生註解轉換為或從 "$comment" 值轉換而來。當同時存在原生註解和 "$comment" 屬性時,此類翻譯的行為是實作相關的。

實作應該將 "$comment" 視為與未知擴充關鍵字相同。它們可以在處理期間的任何時間點去除 "$comment" 值。尤其是,當部署模式的大小是一個問題時,這允許縮短模式。

實作絕不能根據 "$comment" 屬性的存在、缺失或內容採取任何其他動作。尤其是,"$comment" 的值絕不能作為註解結果收集。

9. 應用子模式的詞彙表

本節定義了建議用作其他詞彙表基礎的應用器關鍵字的詞彙表。

不使用 "$vocabulary" 的元模式應被視為需要此詞彙表,就像其 URI 存在且值為 true 一樣。

此詞彙表的目前 URI,稱為應用器詞彙表,為:<https://json-schema.dev.org.tw/draft/2019-09/vocab/applicator>

對應元模式的目前 URI 為:<https://json-schema.dev.org.tw/draft/2019-09/meta/applicator>

詞彙表和中繼綱要 URI 的更新可能會在規範草案之間發佈,以更正錯誤。實現應考慮本規範草案之後和下一個規範草案之前的日期 URI,以表示與此處列出的語法和語意相同。

9.1. 關鍵字獨立性

模式關鍵字通常獨立運作,不會影響彼此的結果。

為了方便模式作者,此詞彙表中的關鍵字有一些例外情況

9.2. 就地應用子模式的關鍵字

這些關鍵字將子模式應用到實例中與套用父模式相同的位置。它們允許以各種方式組合或修改子模式結果。

9.2.1. 使用布林邏輯應用子模式的關鍵字

這些關鍵字對應於用於組合或修改子模式的布林斷言結果的邏輯運算子。它們對註解收集沒有直接影響,儘管它們使相同的註解關鍵字能夠以不同的值應用到實例位置。註解關鍵字定義它們自己組合這些值的規則。

9.2.1.1. allOf

此關鍵字的值必須是非空陣列。陣列的每個項目都必須是有效的 JSON Schema。

如果實例成功地針對此關鍵字的值定義的所有模式進行驗證,則該實例會成功地針對此關鍵字進行驗證。

9.2.1.2. anyOf

此關鍵字的值必須是非空陣列。陣列的每個項目都必須是有效的 JSON Schema。

如果實例成功地針對此關鍵字的值定義的至少一個模式進行驗證,則該實例會成功地針對此關鍵字進行驗證。請注意,當收集註解時,必須檢查所有子模式,以便從每個成功驗證的子模式中收集註解。

9.2.1.3. oneOf

此關鍵字的值必須是非空陣列。陣列的每個項目都必須是有效的 JSON Schema。

如果實例成功地針對此關鍵字的值定義的正好一個模式進行驗證,則該實例會成功地針對此關鍵字進行驗證。

9.2.1.4. not

此關鍵字的值必須是有效的 JSON Schema。

如果實例未能成功地針對此關鍵字定義的模式進行驗證,則該實例對此關鍵字有效。

9.2.2. 有條件地應用子模式的關鍵字

這些關鍵字中的三個共同運作,以根據另一個子模式的結果實現子模式的有條件應用。第四個是特定條件案例的快捷方式。

"if"、"then" 和 "else" 絕不能跨越子模式邊界相互作用。換句話說,"allOf" 的一個分支中的 "if" 絕不能對另一個分支中的 "then" 或 "else" 產生影響。

當 "if"、"then" 或 "else" 不存在時,沒有預設行為。尤其是,它們絕不能被視為好像存在於空模式中,並且當 "if" 不存在時,"then" 和 "else" 都必須完全被忽略。

9.2.2.1. if

此關鍵字的值必須是有效的 JSON Schema。

此關鍵字的子模式的驗證結果對整體驗證結果沒有直接影響。相反地,它控制評估 "then" 或 "else" 關鍵字中的哪一個。

成功地針對此關鍵字的子模式進行驗證的實例,也必須對 "then" 關鍵字的子模式值(如果存在)有效。

未能成功地針對此關鍵字的子模式進行驗證的實例,也必須對 "else" 關鍵字的子模式值(如果存在)有效。

如果正在收集註解,則以通常的方式從此關鍵字的子模式中收集,包括當關鍵字存在而沒有 "then" 或 "else" 時。

9.2.2.2. then

此關鍵字的值必須是有效的 JSON Schema。

當 "if" 存在,且實例成功地針對其子模式進行驗證時,如果實例也成功地針對此關鍵字的子模式進行驗證,則針對此關鍵字的驗證會成功。

當 "if" 不存在,或當實例未能成功地針對其子模式進行驗證時,此關鍵字無效。在這種情況下,為了驗證或註解收集的目的,實作絕不能針對此關鍵字評估實例。

9.2.2.3. else

此關鍵字的值必須是有效的 JSON Schema。

當 "if" 存在,且實例未能成功地針對其子模式進行驗證時,如果實例成功地針對此關鍵字的子模式進行驗證,則針對此關鍵字的驗證會成功。

當缺少 "if" 關鍵字,或實例成功通過其子模式驗證時,此關鍵字無效。在此情況下,為了驗證或收集註釋的目的,實作**必須不得**針對此關鍵字評估實例。

9.2.2.4. dependentSchemas

此關鍵字指定當實例為物件且包含特定屬性時會被評估的子模式。

此關鍵字的值**必須**是一個物件。物件中的每個值**必須**是一個有效的 JSON Schema。

如果物件的鍵是實例中的屬性,則整個實例必須通過子模式的驗證。它的使用取決於屬性的存在。

省略此關鍵字的行為與空物件相同。

9.3. 將子模式應用於子實例的關鍵字

這些關鍵字中的每一個都定義了一個規則,用於將其子模式應用於子實例,特別是物件屬性和陣列項目,並結合它們的結果。

9.3.1. 將子模式應用於陣列的關鍵字

9.3.1.1. items

"items" 的值**必須**是有效的 JSON Schema 或有效的 JSON Schema 的陣列。

如果 "items" 是一個 schema,則當陣列中的所有元素都成功通過該 schema 的驗證時,驗證成功。

如果 "items" 是一個 schema 陣列,則當實例的每個元素都通過位於相同位置的 schema 驗證時(如果有的話),驗證成功。

此關鍵字產生一個註釋值,該值是此關鍵字應用子模式的最大索引。如果子模式已應用於實例的每個索引,例如當 "items" 是一個 schema 時,該值**可能**為布林值 true。

應用於同一實例位置的多個 schema 的 "items" 關鍵字的註釋結果,會通過將任何值為 true 的組合結果設定為 true,否則保留最大的數值來合併。

省略此關鍵字的斷言行為與空 schema 相同。

9.3.1.2. additionalItems

"additionalItems" 的值**必須**是一個有效的 JSON Schema。

此關鍵字的行為取決於同一個 schema 物件中 "items" 的存在和註釋結果。如果 "items" 存在,且其註釋結果是一個數字,則當索引大於該數字的每個實例元素都通過 "additionalItems" 的驗證時,驗證成功。

否則,如果 "items" 不存在或其註釋結果為布林值 true,則**必須**忽略 "additionalItems"。

如果 "additionalItems" 子模式應用於實例陣列中的任何位置,則它會產生一個布林值 true 的註釋結果,類似於 "items" 的單個 schema 行為。如果應用於同一實例位置的任何子模式的任何 "additionalItems" 關鍵字產生了 true 的註釋值,則這些關鍵字的組合結果也為 true。

省略此關鍵字的斷言行為與空 schema 相同。

實作**可能**選擇以另一種產生相同效果的方式實作或最佳化此關鍵字,例如直接檢查 "items" 陣列是否存在和大小。不支援註釋收集的實作**必須**這樣做。

9.3.1.3. unevaluatedItems

"unevaluatedItems" 的值**必須**是一個有效的 JSON Schema。

此關鍵字的行為取決於應用於正在驗證的實例位置的相鄰關鍵字的註釋結果。具體來說,來自 "items" 和 "additionalItems" 的註釋,當它們與 "unevaluatedItems" 關鍵字相鄰時,可以來自這些關鍵字。"unevaluatedItems" 以及這兩個註釋,也可以來自任何和所有相鄰的in-place 應用器關鍵字。這包括但不限於本文檔中定義的 in-place 應用器。

如果存在 "items" 註釋,且其註釋結果是一個數字,並且不存在 "additionalItems" 或 "unevaluatedItems" 註釋,則當索引大於 "items" 註釋的每個實例元素都通過 "unevaluatedItems" 的驗證時,驗證成功。

否則,如果任何 "items"、"additionalItems" 或 "unevaluatedItems" 註釋的值為布林值 true,則**必須**忽略 "unevaluatedItems"。但是,如果這些註釋都不存在,則**必須**將 "unevaluatedItems" 應用於陣列中的所有位置。

這表示在可以評估此關鍵字之前,**必須**先評估 "items"、"additionalItems" 和所有 in-place 應用器。擴充關鍵字的作者**不得**定義需要在評估此關鍵字之前評估的 in-place 應用器。

如果 "unevaluatedItems" 子模式應用於實例陣列中的任何位置,則它會產生一個布林值 true 的註釋結果,類似於 "items" 的單個 schema 行為。如果應用於同一實例位置的任何子模式的任何 "unevaluatedItems" 關鍵字產生了 true 的註釋值,則這些關鍵字的組合結果也為 true。

省略此關鍵字的斷言行為與空 schema 相同。

不收集註釋的實作**必須**在遇到此關鍵字時引發錯誤。

9.3.1.4. contains

此關鍵字的值**必須**是一個有效的 JSON Schema。

如果陣列實例的至少一個元素通過給定 schema 的驗證,則該陣列實例對 "contains" 有效。請注意,在收集註釋時,即使找到第一個匹配項後,也**必須**將子模式應用於每個陣列元素。這是為了確保收集所有可能的註釋。

9.3.2. 將子模式應用於物件的關鍵字

9.3.2.1. properties

"properties" 的值**必須**是一個物件。此物件的每個值**必須**是一個有效的 JSON Schema。

如果對於實例中出現的每個名稱,以及此關鍵字的值中作為名稱出現的每個名稱,該名稱的子實例都成功通過相應 schema 的驗證,則驗證成功。

此關鍵字的註釋結果是由此關鍵字匹配的實例屬性名稱集合。應用於同一實例位置的多個 schema 的 "properties" 關鍵字的註釋結果,會通過取得集合的聯集來合併。

省略此關鍵字的斷言行為與空物件相同。

9.3.2.2. patternProperties

"patternProperties" 的值**必須**是一個物件。此物件的每個屬性名稱**應**根據 ECMA 262 正規表示式方言是一個有效的正規表示式。此物件的每個屬性值**必須**是一個有效的 JSON Schema。

如果對於每個匹配此關鍵字值中作為屬性名稱出現的任何正規表示式的實例名稱,該名稱的子實例都成功通過與匹配的正規表示式對應的每個 schema 的驗證,則驗證成功。

此關鍵字的註釋結果是由此關鍵字匹配的實例屬性名稱集合。應用於同一實例位置的多個 schema 的 "patternProperties" 關鍵字的註釋結果,會通過取得集合的聯集來合併。

省略此關鍵字的斷言行為與空物件相同。

9.3.2.3. additionalProperties

"additionalProperties" 的值**必須**是一個有效的 JSON Schema。

此關鍵字的行為取決於同一個 schema 物件中 "properties" 和 "patternProperties" 的存在和註釋結果。使用 "additionalProperties" 進行驗證僅適用於未出現在 "properties" 或 "patternProperties" 的註釋結果中的實例名稱的子值。

對於所有此類屬性,如果子實例通過 "additionalProperties" schema 的驗證,則驗證成功。

此關鍵字的註釋結果是由此關鍵字的子模式驗證的實例屬性名稱集合。應用於同一實例位置的多個 schema 的 "additionalProperties" 關鍵字的註釋結果,會通過取得集合的聯集來合併。

省略此關鍵字的斷言行為與空 schema 相同。

實作**可能**選擇以另一種產生相同效果的方式實作或最佳化此關鍵字,例如直接檢查 "properties" 中的名稱和 "patternProperties" 中的模式是否與實例屬性集匹配。不支援註釋收集的實作**必須**這樣做。

9.3.2.4. unevaluatedProperties

"unevaluatedProperties" 的值**必須**是一個有效的 JSON Schema。

此關鍵字的行為取決於應用於正在驗證的實例位置的相鄰關鍵字的註釋結果。具體來說,來自 "properties"、"patternProperties" 和 "additionalProperties" 的註釋,當它們與 "unevaluatedProperties" 關鍵字相鄰時,可以來自這些關鍵字。"unevaluatedProperties" 以及這三個註釋,也可以來自任何和所有相鄰的in-place 應用器關鍵字。這包括但不限於本文檔中定義的 in-place 應用器。

使用 "unevaluatedProperties" 進行驗證僅適用於未出現在應用於正在驗證的實例位置的 "properties"、"patternProperties"、"additionalProperties" 或 "unevaluatedProperties" 註釋結果中的實例名稱的子值。

對於所有此類屬性,如果子實例通過 "unevaluatedProperties" schema 的驗證,則驗證成功。

這表示在可以評估此關鍵字之前,**必須**先評估 "properties"、"patternProperties"、"additionalProperties" 和所有 in-place 應用器。擴充關鍵字的作者**不得**定義需要在評估此關鍵字之前評估的 in-place 應用器。

此關鍵字的註釋結果是由此關鍵字的子模式驗證的實例屬性名稱集合。應用於同一實例位置的多個 schema 的 "unevaluatedProperties" 關鍵字的註釋結果,會通過取得集合的聯集來合併。

省略此關鍵字的斷言行為與空 schema 相同。

不收集註釋的實作**必須**在遇到此關鍵字時引發錯誤。

9.3.2.5. propertyNames

"propertyNames" 的值**必須**是一個有效的 JSON Schema。

如果實例是一個物件,則當實例中的每個屬性名稱都通過提供的 schema 的驗證時,此關鍵字驗證成功。請注意,schema 正在測試的屬性名稱始終是一個字串。

省略此關鍵字的行為與空 schema 相同。

10. 輸出格式

JSON Schema 被定義為獨立於平台的。因此,為了提高跨平台的相容性,實作**應**符合標準的驗證輸出格式。本節描述了消費者正確解釋驗證結果所需的最基本要求。

10.1. 格式

JSON Schema 輸出是使用第 4.2.1 節中描述的 JSON Schema 資料實例模型定義的。實作**可能**會根據其特定語言和平台支援的內容偏離此模型,但是**建議**輸出可以通過序列化或其他方式轉換為此處定義的 JSON 格式。

10.2. 輸出格式

本規範定義了四種輸出格式。有關每種格式的要求,請參閱「輸出結構」一節。

實作**應該**至少提供 "flag"、"basic" 或 "detailed" 格式,並且**可以**提供 "verbose" 格式。如果提供一個或多個複雜格式,則**必須**同時提供 "flag" 格式。實作**應該**在其文件中明確說明其支援的格式。

10.3. 最低資訊

除了簡化的 "flag" 輸出之外,額外資訊對於協助偵錯 schema 或實例很有用。每個子結果**應該**至少包含本節中包含的資訊。

包含所有這些組件的單一物件被視為一個輸出單元。

實作**可以**選擇提供額外資訊。

10.3.1. 關鍵字相對位置

遵循驗證路徑的驗證關鍵字的相對位置。該值**必須**以 JSON Pointer 表示,並且**必須**包含任何依參考的應用程式,例如 "$ref" 或 "$recursiveRef"。

#/properties/width/$ref/minimum

                        

請注意,由於包含這些依參考的應用程式關鍵字,此指標可能無法透過正常的 JSON Pointer 處理來解析。

此資訊的 JSON 鍵為 "keywordLocation"。

10.3.2. 關鍵字絕對位置

驗證關鍵字的絕對、已取消參考的位置。該值**必須**使用相關 schema 物件的標準 URI 以絕對 URI 表示,並且**不得**包含依參考的應用程式,例如 "$ref" 或 "$recursiveRef" 作為非終端路徑組件。如果錯誤或註釋是針對該關鍵字(例如無法解析的參考),則它可以以這類關鍵字結尾。

https://example.com/schemas/common#/$defs/count/minimum

                        

僅當相對位置不包含任何參考,或 schema 未將絕對 URI 宣告為其 "$id" 時,此資訊**可以**省略。

此資訊的 JSON 鍵為 "absoluteKeywordLocation"。

10.3.3. 實例位置

正在驗證的實例中 JSON 值的位置。該值**必須**以 URI 片段編碼的 JSON Pointer 表示。

此資訊的 JSON 鍵為 "instanceLocation"。

10.3.4. 錯誤或註釋

驗證產生的錯誤或註釋。

對於錯誤,此規範未定義訊息的特定措辭。實作將需要提供此資訊。

對於註釋,產生註釋的每個關鍵字都會指定其格式。預設情況下,它是關鍵字的值。

失敗驗證的 JSON 鍵為 "error";對於成功的驗證,則為 "annotation"。

10.3.5. 巢狀結果

對於兩個階層式結構,此屬性將保存巢狀錯誤和註釋。

失敗驗證中巢狀結果的 JSON 鍵為 "errors";對於成功的驗證,則為 "annotations"。請注意複數形式,因為具有巢狀結果的關鍵字也可能具有本機錯誤或註釋。

10.4. 輸出結構

輸出**必須**是一個物件,其中包含一個名為 "valid" 的布林屬性。當需要有關結果的額外資訊時,輸出**必須**還包含如下所述的 "errors" 或 "annotations"。

在這些範例中,將使用以下 schema 和實例。

{
  "$id": "https://example.com/polygon",
  "$schema": "https://json-schema.dev.org.tw/draft/2019-09/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
  }
]

                    

此實例將無法通過驗證並產生錯誤,但推導產生註釋的通過 schema 的範例非常簡單。

具體而言,它將產生的錯誤為

請注意,這些範例中描述的錯誤訊息措辭並非此規範的要求。實作**應該**製作為其受眾量身定制的錯誤訊息,或提供允許其使用者製作自己的訊息的範本機制。

10.4.1. Flag

在最簡單的情況下,僅需要滿足 "valid" 有效屬性的布林結果。

{
  "valid": false
}

                        

由於此格式不傳回任何錯誤或註釋,因此**建議**實作使用短路邏輯,以便在可以確定結果後立即傳回失敗或成功。例如,如果 "anyOf" 關鍵字包含五個子 schema,且第二個子 schema 通過,則無需檢查其他三個。邏輯可以簡單地傳回成功。

10.4.2. Basic

"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"
    }
  ]
}

                        

10.4.3. Detailed

"Detailed" 結構基於 schema,對於人類和機器而言都更易讀。以這種方式組織結構可以使錯誤之間的關聯更加明顯。例如,在 "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"
    }
  ]
}

                        

10.4.4. Verbose

"Verbose" 結構是一個完全實現的階層結構,與 schema 的結構完全匹配。此結構在表單產生和驗證中具有應用,其中錯誤的位置很重要。

此結構與 "Detailed" 結構的主要差異在於會傳回所有結果。這包括原本會被移除的子 schema 驗證結果(例如,失敗驗證的註釋、`not` 關鍵字內的成功驗證等)。因此,**建議**每個節點也攜帶一個 `valid` 屬性,以指示該節點的驗證結果。

由於此輸出結構可能相當大,因此此處提供較小的範例以簡潔起見。上述範例的完整輸出結構的 URI 為:<https://json-schema.dev.org.tw/draft/2019-09/output/verbose-example>

// schema
{
  "$id": "https://example.com/polygon",
  "$schema": "https://json-schema.dev.org.tw/draft/2019-09/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."
        }
      ]
    }
  ]
}

                        

10.4.5. 輸出驗證 schema

為了方便起見,已提供 JSON Schema 來驗證實作產生的輸出。其 URI 為:<https://json-schema.dev.org.tw/draft/2019-09/output/schema>

11. 用於超媒體

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

11.1. 連結至 Schema

**建議**由 schema 描述的實例使用 Linked Data Protocol 1.0,第 8.1 節定義的連結關係 "describedby" 來提供連結到可下載的 JSON Schema。

在 HTTP 中,此類連結可以使用 Link 標頭附加至任何回應。此標頭的範例為

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

                    

11.2. 透過媒體類型參數識別 Schema

媒體類型**可以**允許 "schema" 媒體類型參數,這讓 HTTP 伺服器能夠根據 schema 執行內容類型協商。媒體類型參數**必須**是空格分隔的 URI 清單(即相對參考無效)。

使用媒體類型 application/schema-instance+json 時,**必須**提供 "schema" 參數。

使用媒體類型 application/schema+json 時,**可以**提供 "schema" 參數。如果提供,它**應該**包含與 "$schema" 關鍵字識別的 URI 相同的 URI,並且**可以**包含其他 URI。無論是否存在其他或額外的 meta-schema 作為媒體類型參數,"$schema" URI **必須**被視為 schema 的標準 meta-schema。

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

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

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

                    

多個 schema 以空格分隔,並表示該實例符合所有列出的 schema

Content-Type: application/json;
          schema="https://example.com/alice https://example.com/bob"

                    

媒體類型參數也用於 HTTP 的 Accept 請求標頭中

Accept: application/json;
          schema="https://example.com/qiang https://example.com/li",
        application/json;
          schema="https://example.com/kumar"

                    

與 Content-Type 一樣,同一字串中的多個 schema 參數請求一個符合所有列出 schema 的實例。

與 Content-Type 不同,Accept 可以包含多個值,以指示用戶端可以接受多種媒體類型。在上面的範例中,請注意,這兩種媒體類型僅在 schema 參數值上有所不同。這會請求一個符合至少其中一個已識別 schema 的 application/json 表示法。

[CREF14]此段假設我們可以註冊 "schema" 連結關係。我們現在是否應該改為指定類似 "tag:json-schema.org,2017:schema" 的內容? HTTP 也可以在 Link 中傳送 "schema",儘管如果這完全取代媒體類型參數,可能會影響媒體類型語義和 Content-Type 協商

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

                    

11.3. 透過 HTTP 使用

當用於網路上的超媒體系統時,HTTP 通常是用於發布 schema 的首選協定。如果行為不當的用戶端以高於必要的頻率透過網路提取 schema,則可能會對伺服器維護人員造成問題,而實際上可以將 schema 快取一段很長時間。

HTTP 伺服器**應該**在 JSON Schema 上設定長時間快取標頭。HTTP 用戶端**應該**觀察快取標頭,且不在其新鮮度期間內重新請求文件。分散式系統**應該**使用共享快取和/或快取代理。

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" 標頭發出請求,以便伺服器操作員可以聯繫可能行為不端的腳本的所有者。

12. 安全考量

Schema 和實例都是 JSON 值。因此,RFC 8259 中定義的所有安全考量都適用。

實例和 schema 通常都是由不受信任的第三方編寫,並部署在公共網際網路伺服器上。驗證器應注意針對 schema 的剖析和驗證不會消耗過多的系統資源。驗證器**絕對不可**陷入無限迴圈。

伺服器**必須**確保惡意方無法透過上傳具有預先存在或非常相似的 "$id" 的 schema 來更改現有 schema 的功能。

個別的 JSON Schema 詞彙也可能會有它們自己的安全考量。請查閱各自的規格以取得更多資訊。

Schema 作者應謹慎處理 "$comment" 內容,因為惡意的實作可能會違反規範將它們顯示給最終使用者,或者如果預期此行為,則無法將它們移除。

惡意的 schema 作者可能會在 "$comment" 中放置可執行程式碼或其他危險的內容。實作**絕對不可**根據 "$comment" 內容進行剖析或採取其他動作。

13. IANA 考量

13.1. application/schema+json

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

13.2. application/schema-instance+json

JSON Schema 實例的建議 MIME 媒體類型(需要 JSON Schema 特定的媒體類型)定義如下:

14. 參考文獻

14.1. 規範性參考文獻

[ecma262] ECMA 262 規格
[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 月。
[RFC8259] Bray, T., 「JavaScript 物件標記法 (JSON) 資料交換格式」,STD 90, RFC 8259, DOI 10.17487/RFC8259, 2017 年 12 月。
[W3C.REC-ldp-20150226] Speicher, S.Arwe, J.A. Malhotra,「連結資料平台 1.0」,全球資訊網協會建議 REC-ldp-20150226, 2015 年 2 月。

14.2. 參考性參考文獻

[json-hyper-schema] Andrews, H.A. Wright, 「JSON 超級 Schema:JSON 的超媒體註釋詞彙」,網路草案 draft-handrews-json-schema-hyperschema-02, 2017 年 11 月。
[json-schema-validation] Wright, A.Andrews, H.G. Luff,「JSON Schema 驗證:JSON 結構驗證詞彙」,網路草案 draft-handrews-json-schema-validation-02, 2017 年 11 月。
[RFC6596] Ohye, M.J. Kupke,「標準連結關係」,RFC 6596, DOI 10.17487/RFC6596, 2012 年 4 月。
[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 月。
[RFC8288] Nottingham, M.,「網路連結」,RFC 8288, DOI 10.17487/RFC8288, 2017 年 10 月。
[W3C.WD-fragid-best-practices-20121025] Tennison, J.,「片段識別碼和媒體類型定義的最佳實務」,全球資訊網協會 WD WD-fragid-best-practices-20121025, 2012 年 10 月。

附錄 A. Schema 識別範例

請考量以下 schema,其中顯示 "$id" 用於識別根 schema 和各種子 schema,而 "$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 指標(相對於根 schema)的 schema 具有以下基本 URI,並且可由任何列出的 URI 識別,符合上方第 5 節和 8.2.2.2 節。

#(文件根目錄)
標準絕對 URI(也是基本 URI)
https://example.com/root.json
具有指標片段的標準 URI
https://example.com/root.json#

#/$defs/A
基本 URI
https://example.com/root.json
具有純片段的標準 URI
https://example.com/root.json#foo
具有指標片段的標準 URI
https://example.com/root.json#/$defs/A

#/$defs/B
基本 URI
https://example.com/other.json
具有指標片段的標準 URI
https://example.com/other.json#
相對於 root.json 的片段的非標準 URI
https://example.com/root.json#/$defs/B

#/$defs/B/$defs/X
基本 URI
https://example.com/other.json
具有純片段的標準 URI
https://example.com/other.json#bar
具有指標片段的標準 URI
https://example.com/other.json#/$defs/X
相對於 root.json 的片段的非標準 URI
https://example.com/root.json#/$defs/B/$defs/X

#/$defs/B/$defs/Y
基本 URI
https://example.com/t/inner.json
具有純片段的標準 URI
https://example.com/t/inner.json#bar
具有指標片段的標準 URI
https://example.com/t/inner.json#
相對於 other.json 的片段的非標準 URI
https://example.com/other.json#/$defs/Y
相對於 root.json 的片段的非標準 URI
https://example.com/root.json#/$defs/B/$defs/Y

#/$defs/C
基本 URI
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f
具有指標片段的標準 URI
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f#
相對於 root.json 的片段的非標準 URI
https://example.com/root.json#/$defs/C

附錄 B. 操作 schema 文件和參考

已建立各種工具來根據參考 ("$ref") 的顯示方式和位置重新排列 schema 文件。此附錄討論哪些使用案例和動作符合本規範。

B.1. 將 schema 資源捆綁到單個文件中

一組預計一起使用的 schema 資源可以使用它們各自的 schema 文件、全部在同一個 schema 文件中,或是介於兩者之間的任何文件分組粒度來組織。

存在許多工具可以執行各種參考移除。常見的情況是產生一個單一檔案,其中所有參考都可以在該檔案內解析。這通常是為了簡化分發,或是簡化程式碼編寫,讓 JSON Schema 程式庫的各種調用不必追蹤和載入大量資源。

只要所有靜態參考 (例如 "$ref") 都使用解析為標準 URI 的 URI 參考,並且所有 schema 資源在其根 schema 中都有一個絕對 URI 作為 "$id",就可以安全且可逆地執行此轉換。

在滿足這些條件的情況下,每個外部資源都可以複製到 "$defs" 下,而不會破壞資源 schema 物件之間的任何參考,也不會改變驗證或註釋結果的任何方面。"$defs" 下的 schema 名稱不會影響行為(假設它們各自都是唯一的),因為它們不會出現在嵌入資源的標準 URI 中。

B.2. 參考移除並非總是安全

嘗試移除所有參考並產生單個 schema 文件,在所有情況下,並不會產生與原始形式行為相同的 schema。

由於 "$ref" 現在被視為與其他關鍵字相同,且允許在同一個 schema 物件中使用其他關鍵字,因此在所有情況下完全支援非遞迴 "$ref" 移除可能需要相對複雜的 schema 操作。決定或提供一組安全的 "$ref" 移除轉換超出本規範的範圍,因為它們不僅取決於 schema 結構,還取決於預期的用途。

附錄 C. 遞迴 schema 擴充範例

請考量以下兩個 schema,它們描述一個簡單的遞迴樹狀結構,其中樹狀結構中的每個節點都可以有任何類型的 "data" 欄位。第一個 schema 允許並忽略其他實例屬性。第二個 schema 較為嚴格,僅允許 "data" 和 "children" 屬性。也顯示了一個 "data" 拼寫錯誤為 "daat" 的實例範例。

// tree schema, extensible
{
    "$schema": "https://json-schema.dev.org.tw/draft/2019-09/schema",
    "$id": "https://example.com/tree",
    "$recursiveAnchor": true,

    "type": "object",
    "properties": {
        "data": true,
        "children": {
            "type": "array",
            "items": {
                "$recursiveRef": "#"
            }
        }
    }
}

// strict-tree schema, guards against misspelled properties
{
    "$schema": "https://json-schema.dev.org.tw/draft/2019-09/schema",
    "$id": "https://example.com/strict-tree",
    "$recursiveAnchor": true,

    "$ref": "tree",
    "unevaluatedProperties": false
}

// instance with misspelled field
{
    "children": [ { "daat": 1 } ]
}

                

如果我們將「嚴格樹狀」綱要應用到實例,我們會追蹤 "$ref" 到「樹狀」綱要,檢查其 "children" 子綱要,並在其 "items" 子綱要中找到 "$recursiveAnchor"。此時,動態路徑為 "#/$ref/properties/children/items/$recursiveRef"。

此時的基本 URI 為 "https://example.com/tree",因此 "$recursiveRef" 最初解析為 "https://example.com/tree#"。由於 "$recursiveAnchor" 為 true,我們會檢查動態路徑,以查看是否有不同的基本 URI 可用。我們在 "#" 和 "#/$ref" 的動態路徑中找到值為 true 的 "$recursiveAnchor"。

最外層是 "#",這是「嚴格樹狀」綱要的根綱要,因此我們使用其基本 URI "https://example.com/strict-tree",這會為 "$recursiveRef" 產生最終解析的 URI "https://example.com/strict-tree#"。

這樣,「樹狀」綱要中的遞迴會遞迴到「嚴格樹狀」的根,而不是僅將「嚴格樹狀」應用於實例根,而是將「樹狀」應用於實例子項。

附錄 D. 處理詞彙表

D.1. 詞彙表和元綱要作者的最佳實務

如果詞彙表旨在廣泛使用,並可能與其他詞彙表結合使用,則詞彙表作者應注意避免關鍵字名稱衝突。JSON 綱要未提供任何正式的命名空間系統,但也未限制關鍵字名稱,從而允許使用任意數量的命名空間方法。

詞彙表可以相互建立,例如通過定義它們的關鍵字相對於另一個詞彙表中的關鍵字的行為,或者通過使用另一個詞彙表中的關鍵字以及一組受限或擴展的可接受值。並非所有此類詞彙表重用都會產生與其所建立的詞彙表相容的新詞彙表。詞彙表作者應清楚地記錄預期的任何相容性級別(如果有的話)。

元綱要作者不應使用 "$vocabulary" 來組合多個為同一個關鍵字定義衝突語法或語義的詞彙表。由於語義衝突通常無法通過綱要驗證來檢測,因此不希望實作檢測到此類衝突。如果宣告了衝突的詞彙表,則產生的行為未定義。

詞彙表作者應提供元綱要,該元綱要驗證詞彙表關鍵字本身的預期用法。此類元綱要不應禁止其他關鍵字,並且不得禁止來自核心詞彙表的任何關鍵字。

建議元綱要作者使用 "allOf" 關鍵字來引用每個詞彙表的元綱要,儘管其他建構元綱要的機制可能適用於某些使用案例。

元綱要的遞迴性質使得 "$recursiveAnchor" 和 "$recursiveRef" 關鍵字對於擴展現有元綱要特別有用,正如在擴展驗證元綱要的 JSON 超綱要元綱要中所見。

元綱要可以施加額外的約束,包括描述任何詞彙表中不存在的關鍵字,超出與宣告的詞彙表相關聯的元綱要所描述的內容。這允許將使用限制為詞彙表的子集,並驗證不打算重複使用的本地定義的關鍵字。

但是,元綱要不應與它們宣告的任何詞彙表相矛盾,例如通過要求與詞彙表期望不同的 JSON 類型。產生的行為未定義。

用於本地用途且無需在任意實作中測試詞彙表支援的元綱要可以安全地完全省略 "$vocabulary"。

D.2. 帶有詞彙表宣告的範例元綱要

此元綱要明確宣告核心和應用程式詞彙表以及擴展詞彙表,並將它們的元綱要與 "allOf" 組合在一起。擴展詞彙表的元綱要僅描述該詞彙表中的關鍵字,顯示在主範例元綱要之後。

主範例元綱要還通過禁止以 "unevaluated" 為字首的關鍵字來限制應用程式詞彙表的使用,這些關鍵字的實作特別複雜。這不會改變應用程式詞彙表定義的語義或關鍵字集。它僅確保使用此元綱要的綱要嘗試使用以 "unevaluated" 為字首的關鍵字將無法通過此元綱要的驗證。

最後,此元綱要描述了一個關鍵字 "localKeyword" 的語法,該關鍵字不屬於任何詞彙表。據推測,此元綱要的實作人員和使用者將理解 "localKeyword" 的語義。JSON 綱要未定義任何用於在詞彙表之外表達關鍵字語義的機制,這使得它們不適合使用,除非在可以理解它們的特定環境中。

此元綱要組合了多個詞彙表以供一般使用。

{
  "$schema": "https://json-schema.dev.org.tw/draft/2019-09/schema",
  "$id": "https://example.com/meta/general-use-example",
  "$recursiveAnchor": true,
  "$vocabulary": {
    "https://json-schema.dev.org.tw/draft/2019-09/vocab/core": true,
    "https://json-schema.dev.org.tw/draft/2019-09/vocab/applicator": true,
    "https://json-schema.dev.org.tw/draft/2019-09/vocab/validation": true,
    "https://example.com/vocab/example-vocab": true
  },
  "allOf": [
    {"$ref": "https://json-schema.dev.org.tw/draft/2019-09/meta/core"},
    {"$ref": "https://json-schema.dev.org.tw/draft/2019-09/meta/applicator"},
    {"$ref": "https://json-schema.dev.org.tw/draft/2019-09/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.dev.org.tw/draft/2019-09/schema",
  "$id": "https://example.com/meta/example-vocab",
  "$recursiveAnchor": true,
  "$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",
    }
  }
}

                    

如上所示,即使在通用元綱要的 "allOf" 中引用的每個單個詞彙表元綱要都宣告其對應的詞彙表,此新元綱要也必須重新宣告它們。

將核心和驗證規範定義的所有詞彙表組合在一起的標準元綱要,以及將這些規範以及超綱要規範定義的所有詞彙表組合在一起的標準元綱要,展示了其他複雜的組合。這些元綱要的 URI 可以在驗證和超綱要規範中找到。

儘管通用元綱要可以驗證 "minDate" 的語法,但詞彙表定義了 "minDate" 語義含義背後的邏輯。如果不了解語義(在此範例中,實例值必須是等於或晚於在綱要中作為關鍵字值提供的日期的日期),則實作只能驗證語法用法。在這種情況下,這意味著驗證它是否為日期格式化的字串(使用 "pattern" 來確保即使 "format" 僅作為註釋時也驗證它,如 驗證規範中所述)。

附錄 E. 參考和產生式使用案例

儘管預期參考的存在對驗證結果是透明的,但程式碼產生器和 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" 屬性則未被標記。它只是一個具有子欄位的欄位,而不是不同類別的實例。

此使用方式樣式要求註釋與參考在同一個物件中,該物件必須可識別為參考。

附錄 F. 致謝

感謝 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 對該文件的提交和修補。

附錄 G. 變更日誌

[CREF15]此節將在離開 Internet-Draft 狀態之前刪除。

draft-handrews-json-schema-02

draft-handrews-json-schema-01

draft-handrews-json-schema-00

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 (編輯) 電子郵件:[email protected]
Ben Hutton (編輯) Wellcome Sanger Institute 電子郵件:[email protected] URI:https://jsonschema.dev
Greg Dennis 奧克蘭, 紐西蘭 電子郵件:[email protected]