網際網路草案 JSON Schema 驗證 2022 年 6 月
Wright 等人 於 2022 年 12 月 18 日到期 [頁]
工作小組
網際網路工程任務組
網際網路草案
draft-bhutton-json-schema-validation-01
已發布
預期狀態
資訊性
到期
作者
A. Wright, 編輯
H. Andrews, 編輯
B. Hutton, 編輯
Postman

JSON Schema 驗證:JSON 結構驗證的詞彙

摘要

JSON Schema (application/schema+json) 有幾個用途,其中之一是 JSON 實例驗證。本文檔指定了 JSON Schema 的詞彙表,用於描述 JSON 文檔的含義,為使用 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 日到期。

目錄

1. 簡介

JSON Schema 可用於要求給定的 JSON 文件(一個實例)滿足一定數量的條件。這些條件是透過使用本規範中描述的關鍵字來斷言的。此外,還定義了一組關鍵字來協助互動式使用者介面實例的產生。

本規範將使用 JSON Schema 核心 [json-schema] 規範定義的概念、語法和術語。

2. 慣例和術語

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

本規範使用術語「容器實例」來指稱陣列和物件實例。它使用術語「子實例」來指稱陣列元素或物件成員值。

如果此陣列中沒有兩個元素 相等 [json-schema],則陣列值中的元素被認為是唯一的。

3. 概述

JSON Schema 驗證會對實例資料的結構斷言約束。滿足所有斷言約束的實例位置會使用任何包含非斷言資訊(例如描述性中繼資料和使用提示)的關鍵字進行註釋。如果實例中的所有位置都滿足所有斷言約束,則稱該實例對於該結構描述而言有效。

每個結構描述物件都會針對其所適用的每個實例位置獨立進行評估。這大大簡化了驗證器的實作要求,確保他們不需要在整個文件驗證過程中保持狀態。

本規範定義了一組斷言關鍵字,以及一個小的元數據關鍵字詞彙表,可用於使用有用的資訊來註解 JSON 實例。第 7 節關鍵字主要用作註解,但也可以選擇用作斷言。第 8 節關鍵字是用於處理以 JSON 字串形式嵌入的文件的註解。

4. 互通性考量

4.1. 字串實例的驗證

應該注意的是,空字元 (\u0000) 在 JSON 字串中是有效的。要驗證的實例可能包含帶有此字元的字串值,而不管底層程式語言是否能夠處理此類資料。

4.2. 數值實例的驗證

JSON 規範允許任意精度的數字,而 JSON Schema 並未添加任何此類限制。這表示由 JSON Schema 處理的數值實例可以任意大和/或具有任意長的小數部分,而不管底層程式語言是否能夠處理此類資料。

4.3. 正規表示式

使用正規表示式或將實例值限制為正規表示式的關鍵字,受限於JSON Schema Core [json-schema]規範中正規表示式的互通性考量。

5. 元架構

預設 JSON Schema 方言元架構的目前 URI 是 https://json-schema.dev.org.tw/draft/2020-12/schema。為了方便架構作者,此元架構描述了一種方言,該方言由本規範和 JSON Schema Core 規範中定義的所有詞彙組成,以及兩個為過渡期保留的先前關鍵字。下面各節中提供了單獨的詞彙和詞彙元架構 URI。某些詞彙是可選的支援,這在相關章節中有詳細說明。

為了更正錯誤,規範草案之間可能會發佈更新的詞彙和元架構 URI。實作 SHOULD 考慮在本規範草案之後且在下一個草案之前日期的 URI,以表示與此處列出的語法和語義相同。

6. 用於結構驗證的詞彙表

架構中的驗證關鍵字對成功驗證實例施加要求。這些關鍵字都是斷言,沒有任何註解行為。

不使用「$vocabulary」的元架構,應該被認為需要此詞彙表,如同其 URI 存在且值為 true。

此詞彙表的目前 URI(稱為驗證詞彙表)為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/validation>。

對應的元架構的目前 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/validation

6.1. 任何實例類型的驗證關鍵字

6.1.1. type

此關鍵字的值必須是字串或陣列。如果它是陣列,則陣列的元素必須是字串,且必須是唯一的。

字串值必須是六個基本類型之一(「null」、「boolean」、「object」、「array」、「number」或「string」),或「integer」,它符合任何具有零小數部分的數字。

如果「type」的值是字串,則如果實例的類型符合字串值表示的類型,則實例會成功驗證。如果「type」的值是陣列,則如果實例的類型符合陣列中字串所表示的任何類型,則實例會成功驗證。

6.1.2. enum

此關鍵字的值必須是陣列。此陣列 SHOULD 至少有一個元素。陣列中的元素 SHOULD 是唯一的。

如果實例的值等於此關鍵字的陣列值中的其中一個元素,則實例會成功驗證此關鍵字。

陣列中的元素可能是任何類型,包括 null。

6.1.3. const

此關鍵字的值可以是任何類型,包括 null。

使用此關鍵字在功能上等同於具有單個值的「enum」(第 6.1.2 節)

如果實例的值等於關鍵字的值,則實例會成功驗證此關鍵字。

6.2. 數值實例(number 和 integer)的驗證關鍵字

6.2.1. multipleOf

「multipleOf」的值必須是一個數字,嚴格大於 0。

只有當除以此關鍵字的值會得到整數時,數值實例才有效。

6.2.2. maximum

「maximum」的值必須是一個數字,表示數值實例的包含上限。

如果實例是數字,則只有當實例小於或完全等於「maximum」時,此關鍵字才會驗證。

6.2.3. exclusiveMaximum

「exclusiveMaximum」的值必須是一個數字,表示數值實例的排除上限。

如果實例是數字,則只有當實例的值嚴格小於(不等於)「exclusiveMaximum」時,該實例才有效。

6.2.4. minimum

「minimum」的值必須是一個數字,表示數值實例的包含下限。

如果實例是數字,則只有當實例大於或完全等於「minimum」時,此關鍵字才會驗證。

6.2.5. exclusiveMinimum

「exclusiveMinimum」的值必須是一個數字,表示數值實例的排除下限。

如果實例是數字,則只有當實例的值嚴格大於(不等於)「exclusiveMinimum」時,該實例才有效。

6.3. 字串的驗證關鍵字

6.3.1. maxLength

此關鍵字的值必須是非負整數。

如果字串實例的長度小於或等於此關鍵字的值,則該實例符合此關鍵字的驗證。

字串實例的長度定義為 RFC 8259 [RFC8259] 定義的字元數。

6.3.2. minLength

此關鍵字的值必須是非負整數。

如果字串實例的長度大於或等於此關鍵字的值,則該實例符合此關鍵字的驗證。

字串實例的長度定義為 RFC 8259 [RFC8259] 定義的字元數。

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

6.3.3. pattern

此關鍵字的值必須是字串。根據 ECMA-262 正規表示式方言,此字串 SHOULD 是有效的正規表示式。

如果正規表示式成功符合實例,則字串實例會被視為有效。請記住:正規表示式不是隱式錨定的。

6.4. 陣列的驗證關鍵字

6.4.1. maxItems

此關鍵字的值必須是非負整數。

如果陣列實例的大小小於或等於此關鍵字的值,則該實例符合「maxItems」的驗證。

6.4.2. minItems

此關鍵字的值必須是非負整數。

如果陣列實例的大小大於或等於此關鍵字的值,則該實例符合「minItems」的驗證。

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

6.4.3. uniqueItems

此關鍵字的值必須是布林值。

如果此關鍵字的布林值為 false,則實例會成功驗證。如果它的布林值為 true,則如果它的所有元素都是唯一的,則實例會成功驗證。

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

6.4.4. maxContains

此關鍵字的值必須是非負整數。

如果相同的架構物件中不存在「contains」,則此關鍵字無效。

若相鄰的 "contains" [json-schema] 關鍵字的註解結果形式不同,則執行個體陣列針對 "maxContains" 的驗證方式有兩種。第一種方式是,若註解結果為陣列,且該陣列的長度小於或等於 "maxContains" 的值。第二種方式是,若註解結果為布林值 "true",且執行個體陣列的長度小於或等於 "maxContains" 的值。

6.4.5. minContains

此關鍵字的值必須為非負整數。

若相同的綱要物件中不存在 "contains",則此關鍵字無效。

若相鄰的 "contains" [json-schema] 關鍵字的註解結果形式不同,則執行個體陣列針對 "minContains" 的驗證方式有兩種。第一種方式是,若註解結果為陣列,且該陣列的長度大於或等於 "minContains" 的值。第二種方式是,若註解結果為布林值 "true",且執行個體陣列的長度大於或等於 "minContains" 的值。

允許值為 0,但僅適用於設定從 0 到 "maxContains" 值的出現次數範圍。值為 0 會導致 "minContains" 和 "contains" 永遠通過驗證(但驗證仍可能因 "maxContains" 關鍵字而失敗)。

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

6.5. 物件的驗證關鍵字

6.5.1. maxProperties

此關鍵字的值必須為非負整數。

若物件執行個體的屬性數量小於或等於此關鍵字的值,則該物件執行個體針對 "maxProperties" 為有效。

6.5.2. minProperties

此關鍵字的值必須為非負整數。

若物件執行個體的屬性數量大於或等於此關鍵字的值,則該物件執行個體針對 "minProperties" 為有效。

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

6.5.3. required

此關鍵字的值必須為陣列。此陣列中的元素(若有的話)必須為字串,且必須是唯一的。

若陣列中的每個項目都是執行個體中的屬性名稱,則該物件執行個體針對此關鍵字為有效。

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

6.5.4. dependentRequired

此關鍵字的值必須為物件。此物件中的屬性(若有的話)必須為陣列。每個陣列中的元素(若有的話)必須為字串,且必須是唯一的。

此關鍵字指定,若存在特定的其他屬性,則必須存在的屬性。其要求取決於其他屬性的存在。

若執行個體和此關鍵字的值中都出現每個名稱,且對應陣列中的每個項目也都是執行個體中的屬性名稱,則驗證成功。

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

7. 使用 "format" 的語意內容詞彙表

7.1. 前言

單獨的結構驗證可能不足以讓應用程式正確使用某些值。定義 "format" 註解關鍵字是為了讓綱要作者能針對由權威資源(無論是 RFC 或其他外部規範)準確描述的一組固定值傳達語意資訊。

此關鍵字的值稱為格式屬性。它必須是一個字串。格式屬性通常只能驗證給定的一組執行個體類型。如果要驗證的執行個體類型不在這個集合中,則此格式屬性和執行個體的驗證應成功。本節中定義的所有格式屬性都適用於字串,但可以指定格式屬性以適用於核心 JSON 綱要 [json-schema]中定義的資料模型中定義的任何執行個體類型。 請注意,此規格中的 "type" 關鍵字定義了一個不屬於資料模型的 "integer" 類型。因此,格式屬性可以限制為數字,但不能專門限制為整數。但是,數值格式可以與值為 "integer" 的 "type" 關鍵字一起使用,或者可以明確定義為,如果數字不是整數則永遠通過,這與僅適用於整數的行為基本相同。

此詞彙表的當前 URI(稱為格式註解詞彙表)為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/format-annotation>。對應的中繼綱要的當前 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/format-annotation。必須實作對此詞彙表的支援。

除了格式註解詞彙表之外,還有一個次要詞彙表可用於將 "format" 定義為斷言的自訂中繼綱要。格式斷言詞彙表的 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/format-assertion>。對應的中繼綱要的當前 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/format-assertion。實作對格式斷言詞彙表的支援是選用的。

指定格式註解詞彙表和格式斷言詞彙表在功能上等同於僅指定格式斷言詞彙表,因為其要求是格式註解詞彙表的超集。

7.2. 實作要求

"format" 關鍵字的功能由參考的詞彙表定義。

7.2.1. 格式註解詞彙表

如果實作支援註解收集,則必須將 format 的值收集為註解。這可以在綱要驗證不可用或不充分時啟用應用程式層級的驗證。

除了註解之外,實作可以仍然將 "format" 視為斷言,並嘗試驗證值是否符合指定的語意。實作必須提供啟用和停用此類評估的選項,且預設必須停用。實作應記錄其對此類驗證的支援程度。 指定格式註解詞彙表並在實作中啟用驗證不應被視為等同於指定格式斷言詞彙表,因為未指定格式斷言詞彙表時,不要求實作提供完整的驗證支援。

當實作設定為斷言行為時,它:

  • 應針對下面定義的每個格式屬性提供實作特定的最佳驗證;
  • 可以選擇將任何或所有格式屬性的驗證實作為無操作,方法是永遠產生 true 的驗證結果;

這符合實作的當前實際情況,即它們為某些或所有格式屬性提供差異很大的驗證等級,包括完全不驗證。它也旨在鼓勵僅依賴註解行為並在應用程式中執行語意驗證,這是建議的最佳實務。

7.2.2. 格式斷言詞彙表

當使用值 true 宣告格式斷言詞彙表時,實作必須為此規格定義的所有格式提供完整的驗證支援。無法提供完整驗證支援的實作必須拒絕處理綱要。

支援格式斷言詞彙表的實作:

  • 如果實作支援註解收集,則仍必須將 "format" 收集為註解;
  • 必須將 "format" 評估為斷言;
  • 必須為此規格定義的所有格式屬性,以及它識別的任何其他格式屬性實作語法驗證,以使得存在正確類型的可能執行個體值,這些值將無法通過驗證。

由於許多屬性中涉及的複雜性,因此對格式屬性進行最少驗證的要求是有意含糊且允許的。請特別注意,該要求僅限於語法檢查;不應期望實作會傳送電子郵件、嘗試連線到 URL,或以其他方式檢查格式執行個體所識別實體是否存在。 預期對於諸如日期時間之類的簡單格式,語法驗證將會很徹底。對於諸如電子郵件地址之類的複雜格式(它是各種標準的融合,以及隨著時間的推移進行的多次調整,其中包含可能受使用該值的其他應用程式限制的模糊和/或過時的規則),最少的驗證就足夠了。例如,不包含 "@" 的執行個體字串顯然不是有效的電子郵件地址,而包含 7 位元 ASCII 之外的字元的 "email" 或 "hostname" 也顯然無效。

建議實作針對每個格式使用通用的剖析程式庫或著名的正規表示式。實作應清楚地記錄每個格式屬性如何以及在何種程度上進行驗證。

標準核心和驗證元模式第 5 節在其 "$vocabulary" 關鍵字中包含此詞彙,值為 false,因為預設情況下,實作並不需要將此關鍵字作為斷言支援。支援格式詞彙並將值設為 true 會大幅增加程式碼大小,在某些情況下也會增加執行時間,因此並非所有實作都適用。

7.2.3. 自訂格式屬性

實作可以支援自訂格式屬性。除非各方之間達成協議,否則綱要作者不應期望對等實作支援此類自訂格式屬性。實作不得無法收集未知的格式作為註釋。當指定格式斷言詞彙時,實作遇到未知的格式時必須失敗。

詞彙不支援明確宣告關鍵字的不同值集合。由於此限制,以及此關鍵字的歷史性不均勻實作,建議在需要互通性時,於自訂詞彙中定義其他關鍵字,而不是其他格式屬性。

7.3. 定義的格式

7.3.1. 日期、時間和持續時間

這些屬性適用於字串實例。

日期和時間格式名稱源自 RFC 3339, 第 5.6 節 [RFC3339]。持續時間格式來自 RFC 3339 附錄 A 中給出的 ISO 8601 ABNF。

支援格式的實作應該實作對以下屬性的支援:

date-time
如果字串實例根據 "date-time' ABNF 規則(如上所述)是有效的表示形式,則該實例對於此屬性有效。
date
如果字串實例根據 "full-date" ABNF 規則(如上所述)是有效的表示形式,則該實例對於此屬性有效。
time
如果字串實例根據 "full-time" ABNF 規則(如上所述)是有效的表示形式,則該實例對於此屬性有效。
duration
如果字串實例根據 "duration" ABNF 規則(如上所述)是有效的表示形式,則該實例對於此屬性有效。

實作可以支援使用該 RFC 中任何地方定義的其他格式名稱的其他屬性。如果實作 "full-date" 或 "full-time",則必須實作對應的短格式(分別為 "date" 或 "time"),並且必須以相同的方式運作。實作不應定義任何與 RFC 3339 格式相符的擴充屬性,除非它根據該格式的規則進行驗證。目前對於是否需要支援所有 RFC 3339 格式尚未達成共識,因此這種保留命名空間的方法將鼓勵實驗,而無需承諾整個集合。格式實作要求將變得更具彈性,或者這些要求可能會被提升為完全指定的屬性或被刪除。

7.3.2. 電子郵件地址

這些屬性適用於字串實例。

如果字串實例是有效的網際網路電子郵件地址,則該實例對於這些屬性有效,如下所示:

email
RFC 5321, 第 4.1.2 節 [RFC5321] 中 "Mailbox" ABNF 規則所定義。
idn-email
RFC 6531, 第 3.3 節 [RFC6531] 中擴充的 "Mailbox" ABNF 規則所定義。

請注意,所有對於 "email" 屬性有效的字串也對於 "idn-email" 屬性有效。

7.3.3. 主機名稱

這些屬性適用於字串實例。

如果字串實例是網際網路主機名稱的有效表示形式,則該實例對於這些屬性有效,如下所示:

hostname
RFC 1123, 第 2.1 節 [RFC1123] 所定義,包括使用 RFC 5891, 第 4.4 節 [RFC5891] 中指定的 Punycode 演算法產生的主機名稱。
idn-hostname
如 RFC 1123(對於主機名稱)所定義,或如 RFC 5890, 第 2.3.2.3 節 [RFC5890] 所定義的國際化主機名稱。

請注意,所有對於 "hostname" 屬性有效的字串也對於 "idn-hostname" 屬性有效。

7.3.4. IP 位址

這些屬性適用於字串實例。

如果字串實例是 IP 位址的有效表示形式,則該實例對於這些屬性有效,如下所示:

ipv4
根據 RFC 2673, 第 3.2 節 [RFC2673] 中定義的 "dotted-quad" ABNF 語法的 IPv4 位址。
ipv6
RFC 4291, 第 2.2 節 [RFC4291] 中定義的 IPv6 位址。

7.3.5. 資源識別碼

這些屬性適用於字串實例。

uri
如果字串實例是有效的 URI,根據 [RFC3986],則該實例對於此屬性有效。
uri-reference
如果字串實例是有效的 URI 參考(URI 或相對參考),根據 [RFC3986],則該實例對於此屬性有效。
iri
如果字串實例是有效的 IRI,根據 [RFC3987],則該實例對於此屬性有效。
iri-reference
如果字串實例是有效的 IRI 參考(IRI 或相對參考),根據 [RFC3987],則該實例對於此屬性有效。
uuid
如果字串實例是 UUID 的有效字串表示形式,根據 [RFC4122],則該實例對於此屬性有效。

請注意,所有有效的 URI 都是有效的 IRI,並且所有有效的 URI 參考也是有效的 IRI 參考。

另請注意,"uuid" 格式適用於純 UUID,而非 URN 中的 UUID。一個範例是 "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"。對於作為 URN 的 UUID,請使用 "uri" 格式,並使用 "^urn:uuid:" 的 "pattern" 正則表達式來指示 URI 方案和 URN 命名空間。

7.3.6. uri-template

此屬性適用於字串實例。

如果字串實例是有效的 URI 範本(任何層級),根據 [RFC6570],則該實例對於此屬性有效。

請注意,URI 範本可用於 IRI;沒有單獨的 IRI 範本規範。

7.3.7. JSON 指標

這些屬性適用於字串實例。

json-pointer
如果字串實例是 JSON 指標的有效 JSON 字串表示形式,根據 RFC 6901, 第 5 節 [RFC6901],則該實例對於此屬性有效。
relative-json-pointer
如果字串實例是有效的 相對 JSON 指標 [relative-json-pointer],則該實例對於此屬性有效。

為了允許絕對和相對 JSON 指標,請使用 "anyOf" 或 "oneOf" 來表示對任一格式的支援。

7.3.8. regex

此屬性適用於字串實例。

一個正則表達式,應該根據 ECMA-262 [ecma262] 正則表達式方言有效。

驗證格式的實作必須至少接受此規範的正則表達式第 4.3 節部分中定義的 ECMA-262 子集,並且應該接受所有有效的 ECMA-262 表達式。

8. 字串編碼資料內容的詞彙

8.1. 前言

本節中定義的註釋表示實例包含以 JSON 字串編碼的非 JSON 資料。

這些屬性提供了額外的資訊,用於將 JSON 資料解讀為豐富的多媒體文件。它們描述了內容的類型、編碼方式,以及/或者如何驗證。它們的功能並非驗證斷言;格式錯誤的字串編碼文件「不得」導致包含該文件的實例被視為無效。

沒有使用 "$vocabulary" 的元架構,應被視為要求此詞彙表,如同其 URI 存在且值為 true 一樣。

此詞彙表(稱為 Content 詞彙表)目前的 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/content>。

對應的元架構目前的 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/content

8.2. 實作要求

由於安全性和效能考量,以及可能內容類型的開放性,實作「不得」預設自動解碼、解析和/或驗證字串內容。這也額外支援了嵌入式文件的使用案例,這些文件旨在由處理包含文件的不同消費者處理。

本節中的所有關鍵字僅適用於字串,對其他資料類型無效。

實作「可以」提供自動解碼、解析和/或驗證字串內容的功能。但是,「不得」預設執行這些操作,並且「必須」將每個字串編碼文件的驗證結果與封閉文件分開提供。此過程「應」等同於針對原始架構完整評估實例,然後使用註解來解碼、解析和/或驗證每個字串編碼文件。目前,執行和返回來自此自動解碼、解析和驗證功能的已解析資料和/或驗證結果的確切機制尚未指定。如果此類功能被證明受歡迎,則可能會在未來的草案中更詳細地指定。

另請參閱安全考量第 10 節章節,了解根據這些關鍵字自動處理實例字串可能引入的漏洞。

8.3. contentEncoding

如果實例值是一個字串,則此屬性定義該字串「應」被解讀為編碼的二進位資料,並使用此屬性命名的編碼進行解碼。

RFC 4648 [RFC4648]中列出了指示 base 16、32 和 64 編碼的可能值及其多種變體。此外,RFC 2045 [RFC2045] 的 6.7 和 6.8 節提供了 MIME 中使用的編碼。此關鍵字源自 MIME 的 Content-Transfer-Encoding 標頭,該標頭旨在將二進位資料映射到 ASCII 字元。它與 HTTP 的 Content-Encoding 標頭無關,後者用於編碼(例如壓縮或加密)HTTP 請求和回應的內容。

由於 RFC 中都定義了 "base64",因此「應」採用 RFC 4648 中的定義,除非該字串明確旨在用於 MIME 環境。請注意,所有這些編碼都會產生僅由 7 位 ASCII 字元組成的字串。因此,此關鍵字對於包含該範圍之外字元的字串沒有意義。

如果缺少此關鍵字,但存在 "contentMediaType",則表示該編碼是身分編碼,這意味著為了在 UTF-8 字串中表示內容,不需要進行轉換。

此屬性的值「必須」為字串。

8.4. contentMediaType

如果實例是一個字串,則此屬性表示字串內容的媒體類型。如果存在 "contentEncoding",則此屬性描述已解碼的字串。

此屬性的值「必須」為字串,該字串「必須」為媒體類型,如 RFC 2046 [RFC2046] 中所定義。

8.5. contentSchema

如果實例是一個字串,並且存在 "contentMediaType",則此屬性包含一個描述字串結構的架構。

此關鍵字「可以」與任何可以映射到 JSON Schema 資料模型的媒體類型一起使用。

此屬性的值「必須」是有效的 JSON 架構。如果不存在 "contentMediaType",則「應」忽略它。

8.6. 範例

以下是一個範例架構,說明了 "contentEncoding" 和 "contentMediaType" 的用法:

{
    "type": "string",
    "contentEncoding": "base64",
    "contentMediaType": "image/png"
}

此架構描述的實例預期為字串,並且它們的值應可解讀為 base64 編碼的 PNG 圖像。

另一個範例:

{
    "type": "string",
    "contentMediaType": "text/html"
}

此架構描述的實例預期為包含 HTML 的字串,並使用 JSON 字串解碼成的任何字元集。根據 RFC 8259 [RFC8259] 的 8.1 節,在完全封閉的系統之外,這「必須」是 UTF-8。

此範例描述了一個使用 HMAC SHA-256 演算法進行 MACed 的 JWT,並且在其聲明集中需要 "iss" 和 "exp" 欄位。

{
    "type": "string",
    "contentMediaType": "application/jwt",
    "contentSchema": {
        "type": "array",
        "minItems": 2,
        "prefixItems": [
            {
                "const": {
                    "typ": "JWT",
                    "alg": "HS256"
                }
            },
            {
                "type": "object",
                "required": ["iss", "exp"],
                "properties": {
                    "iss": {"type": "string"},
                    "exp": {"type": "integer"}
                }
            }
        ]
    }
}

請注意,"contentEncoding" 沒有出現。雖然 "application/jwt" 媒體類型使用了 base64url 編碼,但這由媒體類型定義,該類型確定 JWT 字串如何解碼為兩個 JSON 資料結構的列表:首先是標頭,然後是 payload。由於 JWT 媒體類型確保 JWT 可以用 JSON 字串表示,因此無需進一步編碼或解碼。

9. 基本元資料註解的詞彙表

這些通用註解關鍵字提供了常用資訊,用於文件編寫和使用者介面顯示目的。它們並非旨在形成一套全面的功能。相反,可以為更複雜的基於註解的應用程式定義額外的詞彙表。

沒有使用 "$vocabulary" 的元架構,應被視為要求此詞彙表,如同其 URI 存在且值為 true 一樣。

此詞彙表(稱為 Meta-Data 詞彙表)目前的 URI 為:<https://json-schema.dev.org.tw/draft/2020-12/vocab/meta-data>。

對應的元架構目前的 URI 為:https://json-schema.dev.org.tw/draft/2020-12/meta/meta-data

9.1. "title" 和 "description"

這兩個關鍵字的值都「必須」為字串。

這兩個關鍵字都可用於裝飾使用者介面,並提供有關此使用者介面產生之資料的資訊。標題最好簡短,而描述將提供有關此架構描述之實例用途的說明。

9.2. "default"

對此關鍵字的值沒有限制。當此關鍵字的多個出現次數適用於單個子實例時,實作「應」移除重複項。

此關鍵字可用於提供與特定架構關聯的預設 JSON 值。建議預設值針對關聯的架構有效。

9.3. "deprecated"

此關鍵字的值「必須」為布林值。當此關鍵字的多個出現次數適用於單個子實例時,如果任何出現次數指定了 true 值,則應用程式「應」將該實例位置視為已棄用。

如果 "deprecated" 的值為布林值 true,則表示應用程式「應」避免使用宣告的屬性。這「可能」表示該屬性將在未來被移除。

包含 "deprecated" 且值為 true 的根架構表示正在描述的整個資源「可能」在未來被移除。

"deprecated" 關鍵字適用於包含該關鍵字的架構物件成功套用的每個實例位置。這可能會導致每個陣列項目或物件屬性都被棄用,即使包含的陣列或物件沒有被棄用。

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

9.4. "readOnly" 和 "writeOnly"

這些關鍵字的值「必須」為布林值。當這些關鍵字的多個出現次數適用於單個子實例時,如果任何出現次數指定了 true 值,則產生的行為「應」與 true 值相同,否則「應」與 false 值相同。

如果 "readOnly" 的值為布林值 true,則表示實例的值由擁有權限的機構專門管理,並且應用程式嘗試修改此屬性值的行為預期會被該擁有權限的機構忽略或拒絕。

如果整個文件都被標記為 "readOnly",則在將其傳送到擁有權限的機構時,「可以」忽略實例文件,或者「可能」會導致錯誤,由該機構自行決定。

如果 "writeOnly" 的值為布林值 true,則表示當從擁有權限的機構檢索實例時,該值永遠不會出現。當將其傳送到擁有權限的機構以更新或建立文件(或其代表的資源)時,它可能會存在,但它不會包含在任何更新或新建立的實例版本中。

如果整個文件都被標記為 "writeOnly",則「可以」將實例文件返回為某種空白文件,或者「可能」會在檢索時產生錯誤,或者檢索請求被忽略,由該機構自行決定。

例如,"readOnly" 將用於將資料庫產生的序號標記為唯讀,而 "writeOnly" 將用於將密碼輸入欄位標記為唯寫。

這些關鍵字可用於協助使用者介面實例產生。特別是,應用程式「可以」選擇使用一個 widget,該 widget 會隱藏唯寫欄位在輸入時的值。

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

9.5. "examples"

此關鍵字的值「必須」為陣列。對陣列中的值沒有限制。當此關鍵字的多個出現次數適用於單個子實例時,實作「必須」提供所有值的扁平陣列,而不是陣列的陣列。

此關鍵字可用於提供與特定綱要相關聯的 JSON 範例值,以說明其用法。建議這些值對於相關聯的綱要是有效的。

實作時可以將「default」的值(如果存在)用作額外的範例。如果缺少「examples」,仍可以這種方式使用「default」。

10. 安全性考量

JSON Schema 驗證定義了 JSON Schema 核心的詞彙,並涵蓋了其中列出的所有安全性考量。

JSON Schema 驗證允許使用正規表示式,其具有許多不同(通常不相容)的實作方式。某些實作方式允許嵌入任意程式碼,這超出 JSON Schema 的範圍,且絕對不允許。正規表示式也經常被設計成運算成本極高(所謂的「災難性回溯」),導致阻斷服務攻擊。

支援根據「contentEncoding」和/或「contentMediaType」驗證或以其他方式評估實例字串資料的實作,有根據誤導性資訊以不安全方式評估資料的風險。應用程式可以透過僅在綱要和實例之間建立關係(例如,它們共用相同的權限)時才執行此類處理來降低此風險。

媒體類型或編碼的處理受限於該媒體類型或編碼的安全性考量。例如,當處理 JSON 字串中編碼的 JavaScript 或 ECMAScript 時,適用RFC 4329 腳本媒體類型 [RFC4329]的安全性考量。

11. 參考文獻

11.1. 規範性參考文獻

[RFC2119]
Bradner, S., 「在 RFC 中用於表示需求等級的關鍵字」, BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>
[RFC1123]
Braden, R., Ed., 「網際網路主機的需求 - 應用程式和支援」, STD 3, RFC 1123, DOI 10.17487/RFC1123, , <https://www.rfc-editor.org/info/rfc1123>
[RFC2045]
Freed, N.N. Borenstein, 「多用途網際網路郵件擴充 (MIME) 第一部分:網際網路訊息主體格式」, RFC 2045, DOI 10.17487/RFC2045, , <https://www.rfc-editor.org/info/rfc2045>
[RFC2046]
Freed, N.N. Borenstein, 「多用途網際網路郵件擴充 (MIME) 第二部分:媒體類型」, RFC 2046, DOI 10.17487/RFC2046, , <https://www.rfc-editor.org/info/rfc2046>
[RFC2673]
Crawford, M., 「網域名稱系統中的二進位標籤」, RFC 2673, DOI 10.17487/RFC2673, , <https://www.rfc-editor.org/info/rfc2673>
[RFC3339]
Klyne, G.C. Newman, 「網際網路上的日期和時間:時間戳記」, RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/info/rfc3339>
[RFC3986]
Berners-Lee, T., Fielding, R.L. Masinter, 「統一資源識別符號 (URI):通用語法」, STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>
[RFC3987]
Duerst, M.M. Suignard, 「國際化資源識別符號 (IRI)」, RFC 3987, DOI 10.17487/RFC3987, , <https://www.rfc-editor.org/info/rfc3987>
[RFC4122]
Leach, P., Mealling, M.R. Salz, 「通用唯一識別符號 (UUID) URN 命名空間」, RFC 4122, DOI 10.17487/RFC4122, , <https://www.rfc-editor.org/info/rfc4122>
[RFC4291]
Hinden, R.S. Deering, 「IP 第 6 版定址架構」, RFC 4291, DOI 10.17487/RFC4291, , <https://www.rfc-editor.org/info/rfc4291>
[RFC4648]
Josefsson, S., 「Base16、Base32 和 Base64 資料編碼」, RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/info/rfc4648>
[RFC5321]
Klensin, J., 「簡易郵件傳輸協定」, RFC 5321, DOI 10.17487/RFC5321, , <https://www.rfc-editor.org/info/rfc5321>
[RFC5890]
Klensin, J., 「應用程式的國際化網域名稱 (IDNA):定義和文件框架」, RFC 5890, DOI 10.17487/RFC5890, , <https://www.rfc-editor.org/info/rfc5890>
[RFC5891]
Klensin, J., 「應用程式的國際化網域名稱 (IDNA):協定」, RFC 5891, DOI 10.17487/RFC5891, , <https://www.rfc-editor.org/info/rfc5891>
[RFC6570]
Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.D. Orchard, 「URI 範本」, RFC 6570, DOI 10.17487/RFC6570, , <https://www.rfc-editor.org/info/rfc6570>
[RFC6531]
Yao, J.W. Mao, 「國際化電子郵件的 SMTP 擴充」, RFC 6531, DOI 10.17487/RFC6531, , <https://www.rfc-editor.org/info/rfc6531>
[RFC6901]
Bryan, P., Ed., Zyp, K.M. Nottingham, Ed., 「JavaScript 物件表示法 (JSON) 指標」, RFC 6901, DOI 10.17487/RFC6901, , <https://www.rfc-editor.org/info/rfc6901>
[RFC8259]
Bray, T., Ed., 「JavaScript 物件表示法 (JSON) 資料交換格式」, STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/info/rfc8259>
[ecma262]
「ECMA-262,第 11 版規格」, , <https://262.ecma-international.org/5.1/>
[relative-json-pointer]
Luff, G., Andrews, H.B. Hutton, Ed., 「相對 JSON 指標」, 正在進行中, 網際網路草案,draft-handrews-relative-json-pointer-01, , <https://datatracker.ietf.org/doc/html/draft-handrews-relative-json-pointer-01>
[json-schema]
Wright, A., Andrews, H., Hutton, B.G. Dennis, 「JSON Schema:用於描述 JSON 文件的媒體類型」, 正在進行中, 網際網路草案,draft-bhutton-json-schema-01, , <https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-01>

11.2. 參考性參考文獻

[RFC4329]
Hoehrmann, B., 「腳本媒體類型」, RFC 4329, DOI 10.17487/RFC4329, , <https://www.rfc-editor.org/info/rfc4329>

附錄 A. 從驗證移至核心的關鍵字

從本草案開始,一些關鍵字已從本文檔移至核心規格 [json-schema]中,在某些情況下會重新命名或進行其他變更。這會影響以下先前的驗證關鍵字:

「definitions」
已重新命名為「$defs」以符合「$ref」並縮短輸入時間。綱要詞彙作者不應定義具有不同行為的「definitions」關鍵字,以避免使仍然使用舊名稱的綱要失效。雖然此文檔引用的單一詞彙的元綱要中不存在「definitions」,但它仍存在於預設元綱要中,並且實作應假設在使用該元綱要時,「$defs」和「definitions」具有相同的行為。
「allOf」、「anyOf」、「oneOf」、「not」、「if」、「then」、「else」、「items」、「additionalItems」、「contains」、「propertyNames」、「properties」、「patternProperties」、「additionalProperties」
所有這些關鍵字都會將子綱要套用至實例,並合併其結果,而不會斷言它們自己的任何條件。如果沒有斷言關鍵字,這些應用程式只能透過使用 false 布林綱要,或反轉 true 布林綱要(或等效綱要物件)的結果來導致斷言失敗。因此,它們最好被定義為驗證、超綱要和擴充詞彙都可以基於的通用機制。
「dependencies」
此關鍵字具有兩種不同的行為模式,這使得實作和推理都相對具有挑戰性。綱要表單已移至核心,並重新命名為「dependentSchemas」,作為應用程式詞彙的一部分。它類似於「properties」,只是它不是將其子綱要套用至屬性值,而是將其套用至包含該屬性的物件。此處保留屬性名稱陣列表單,並重新命名為「dependentRequired」,因為它是一個斷言,是條件使用「required」斷言關鍵字的捷徑。

附錄 B. 致謝

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

附錄 C. 變更日誌

本節將在離開 Internet-Draft 狀態前移除。

draft-bhutton-json-schema-validation-01
  • 改進並闡明 "minContains" 關鍵字的說明。
  • 移除使用 "production",改用 "ABNF 規則"。
draft-bhutton-json-schema-validation-00
  • 修正電子郵件格式 RFC 參考,應為 5321 而非 5322。
  • 闡明了 "contentEncoding" 值的集合和意義。
  • 參考 ECMA-262 第 11 版以取得正規表示式的支援。
  • 將 "format" 分割為僅限註解的詞彙和斷言詞彙。
  • 當適用於陣列時,闡明 "deprecated"。
draft-handrews-json-schema-validation-02
  • 將關鍵字分組為正式詞彙。
  • 根據詞彙更新 "format" 的實作要求。
  • 預設情況下,"format" 不應驗證,但可以啟用驗證。
  • 詞彙宣告可用於要求 "format" 驗證。
  • 將 "definitions" 移動到核心規範,作為 "$defs"。
  • 將應用程式關鍵字移動到核心規範。
  • 將 "dependencies" 的陣列形式重新命名為 "dependentRequired",將架構形式移動到核心規範。
  • 指定所有 "content*" 關鍵字為註解,而非斷言。
  • 新增 "contentSchema" 以允許將架構應用於字串編碼的文檔。
  • 也允許在 "contentEncoding" 中使用 RFC 4648 編碼。
  • 新增 "minContains" 和 "maxContains"。
  • 更新 "hostname" 和 "idn-hostname" 的 RFC 參考。
  • 新增 "uuid" 和 "duration" 格式。
draft-handrews-json-schema-validation-01
  • 此草案純粹是澄清,沒有功能上的變更。
  • 提供在 "not" 和類似情況下忽略註解的一般原則。
  • 闡明 "if"/"then"/"else" 驗證交互作用。
  • 闡明 "if"/"then"/"else" 對於註解的行為。
  • 次要的格式化和交叉參考改進。
draft-handrews-json-schema-validation-00
  • 新增 "if"/"then"/"else"。
  • 根據核心規範將關鍵字分類為斷言或註解。
  • 警告未來可能會移除 "dependencies"。
  • 將驗證關鍵字分組到子部分,以提高可讀性。
  • 將 "readOnly" 從超架構移動到驗證元數據。
  • 新增 "writeOnly"。
  • 新增字串編碼的媒體章節,包含先前的超架構 "media" 關鍵字。
  • 恢復 "regex" 格式(移除是無意的)。
  • 新增 "date" 和 "time" 格式,並保留額外的 RFC 3339 格式名稱。
  • I18N 格式:"iri"、"iri-reference"、"idn-hostname"、"idn-email"。
  • 闡明 "json-pointer" 格式表示字串編碼,而非 URI 片段。
  • 修正了反轉 "minimum" 和 "exclusiveMinimum" 意義的錯字。
  • 將格式語法參考移動到規範性參考中。
  • JSON 是一項規範性要求。
draft-wright-json-schema-validation-01
  • 標準化使用連字符號的格式名稱和完整單字("uriref" 變成 "uri-reference")。
  • 新增格式 "uri-template" 和 "json-pointer"。
  • 將 "exclusiveMaximum"/"exclusiveMinimum" 從 "maximum"/"minimum" 的布林修飾符變更為獨立的數值欄位。
  • 將 additionalItems/items 分割成兩個部分。
  • 重新設計 properties/patternProperties/additionalProperties 的定義。
  • 新增 "examples" 關鍵字。
  • 新增 "contains" 關鍵字。
  • 允許空的 "required" 和 "dependencies" 陣列。
  • 修正 "type" 參考至基本類型。
  • 新增 "const" 關鍵字。
  • 新增 "propertyNames" 關鍵字。
draft-wright-json-schema-validation-00
  • 新增額外的安全性考量。
  • 移除參考「最新版本」的元架構,改用編號版本。
  • 為簡潔起見,重新措辭許多關鍵字定義。
  • 新增 "uriref" 格式,該格式也允許相對 URI 參考。
draft-fge-json-schema-validation-00
  • 初始草案。
  • 從 v3 草案中挽救。
  • 重新定義 "required" 關鍵字。
  • 移除 "extends"、"disallow"。
  • 新增 "anyOf"、"allOf"、"oneOf"、"not"、"definitions"、"minProperties"、"maxProperties"。
  • "dependencies" 成員值不能再是單一字串;屬性依賴陣列中至少需要一個元素。
  • 將 "divisibleBy" 重新命名為 "multipleOf"。
  • "type" 陣列不能再有架構;移除 "any" 作為可能的值。
  • 重新設計 "format" 章節;使支援成為可選。
  • "format":移除屬性 "phone"、"style"、"color";將 "ip-address" 重新命名為 "ipv4";為所有屬性新增參考。
  • 提供計算陣列/物件實例的架構演算法。
  • 新增互操作性考量。

作者地址

Austin Wright (編輯)
Henry Andrews (編輯)
Ben Hutton (編輯)
Postman