參考

物件

物件是 JSON 中的映射類型。它們將「鍵」映射到「值」。在 JSON 中,「鍵」必須始終是字串。這些配對中的每一個通常都稱為「屬性」。

特定語言資訊:
Python
Ruby
Objective-C
Swift

在 Python 中,「物件」類似於 dict 類型。然而,一個重要的區別是,雖然 Python 字典可以使用任何可雜湊的內容作為鍵,但在 JSON 中,所有鍵都必須是字串。

不要混淆這裡「物件」這個詞的兩種用法:Python 使用 object 這個詞來表示所有事物的通用基類,而在 JSON 中,它僅用於表示從字串鍵到值的映射。

schema
{ "type": "object" }
資料
{ "key": "value", "another_key": "another_value"}
符合 schema
資料
{ "Sun": 1.9891e30, "Jupiter": 1.8986e27, "Saturn": 5.6846e26, "Neptune": 10.243e25, "Uranus": 8.6810e25, "Earth": 5.9736e24, "Venus": 4.8685e24, "Mars": 6.4185e23, "Mercury": 3.3022e23, "Moon": 7.349e22, "Pluto": 1.25e22}
符合 schema

使用非字串作為鍵是無效的 JSON

資料
{ 0.01: "cm", 1: "m", 1000: "km"}
不符合綱要
資料
"不是物件"
不符合綱要
資料
["An", "array", "not", "an", "object"]
不符合綱要

屬性

物件的屬性(鍵值對)是使用 properties 關鍵字 來定義的。 properties 的值是一個物件,其中每個鍵都是屬性的名稱,而每個值都是用來驗證該屬性的綱要。任何不符合 properties 關鍵字中任何屬性名稱的屬性,都會被此關鍵字忽略。

請參閱額外屬性未評估的屬性,了解如何禁止使用不符合 properties 中任何屬性名稱的屬性。

例如,假設我們想為一個由號碼、街道名稱和街道類型組成的地址定義一個簡單的綱要。

schema
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }}
資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }
符合 schema

// 如果我們提供的數字類型錯誤,則為無效

資料
{ "number": "1600", "street_name": "Pennsylvania", "street_type": "Avenue" }
不符合綱要

預設情況下,省略屬性是有效的。請參閱必要屬性

資料
{ "number": 1600, "street_name": "Pennsylvania" }
符合 schema

依此類推,即使是空物件也是有效的

資料
{ }
符合 schema

預設情況下,提供額外的屬性是有效的

資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }
符合 schema

模式屬性

有時候,您可能想要表示,給定特定類型的屬性名稱,其值應符合特定的綱要。這就是 patternProperties 的用處:它將正規表示式對應到綱要。如果屬性名稱符合給定的正規表示式,則屬性值必須根據對應的綱要進行驗證。

正規表示式並非錨定的。這表示在為 patternProperties 定義正規表示式時,請務必注意,表示式可能會在屬性名稱內的任何位置符合。例如,正規表示式 "p" 會符合任何屬性名稱中包含 p 的名稱,例如 "apple",而不僅是名稱僅為 "p" 的屬性。因此,通常將正規表示式放在 ^...$ 中會比較不令人困惑,例如 "^p$"

在此範例中,任何名稱以字首 S_ 開頭的屬性都必須是字串,任何以字首 I_ 開頭的屬性都必須是整數。任何不符合任一正規表示式的屬性都會被忽略。

schema
{ "type": "object", "patternProperties": { "^S_": { "type": "string" }, "^I_": { "type": "integer" } }}
資料
{ "S_25": "This is a string" }
符合 schema
資料
{ "I_0": 42 }
符合 schema

如果名稱以 S_ 開頭,則必須是字串

資料
{ "S_0": 42 }
不符合綱要

如果名稱以 I_ 開頭,則必須是整數

資料
{ "I_42": "This is a string" }
不符合綱要

這是一個不符合任何正規表達式的鍵

資料
{ "keyword": "value" }
符合 schema

額外屬性

additionalProperties 關鍵字用於控制額外內容的處理,也就是說,名稱未在 properties 關鍵字中列出,或是不符合 patternProperties 關鍵字中任何正規表達式的屬性。預設情況下,允許任何額外屬性。

additionalProperties 關鍵字的值是一個 schema,用於驗證 實例 中任何不符合 propertiespatternProperties 的屬性。將 additionalProperties schema 設定為 false 表示不允許任何額外屬性。

沿用屬性中的範例,但這次將 additionalProperties 設定為 false

schema
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": false}
資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }
符合 schema

由於 additionalPropertiesfalse,因此額外的「direction」屬性會使該物件失效。

資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }
不符合綱要

您可以使用非布林值架構,對實例的額外屬性設定更複雜的約束。例如,可以允許額外屬性,但前提是它們的值必須是字串。

schema
{ "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": { "type": "string" }}
資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" }
符合 schema

這是有效的,因為額外屬性的值是字串。

資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "direction": "NW" }
符合 schema

這是無效的,因為額外屬性的值不是字串。

資料
{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue", "office_number": 201 }
不符合綱要

您可以將 additionalPropertiespropertiespatternProperties 結合使用。在以下範例中,根據來自 patternProperties 的範例,我們新增了一個 "builtin" 屬性,該屬性必須是一個數字,並宣告所有額外的屬性(既不是由 properties 定義,也不是由 patternProperties 匹配的屬性)都必須是字串。

schema
{ "type": "object", "properties": { "builtin": { "type": "number" } }, "patternProperties": { "^S_": { "type": "string" }, "^I_": { "type": "integer" } }, "additionalProperties": { "type": "string" }}
資料
{ "builtin": 42 }
符合 schema

這是一個不符合任何正規表達式的鍵

資料
{ "keyword": "value" }
符合 schema

它必須是一個字串

資料
{ "keyword": 42 }
不符合綱要

擴展封閉的綱要

請注意,additionalProperties 只會識別與自身在同一個子模式中宣告的屬性。因此,additionalProperties 可能會限制您使用組合關鍵字(如allOf)「擴展」模式。在以下範例中,我們可以看到additionalProperties 如何導致擴展地址模式範例的嘗試失敗。

schema
{ "allOf": [ { "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"], "additionalProperties": false } ],
"properties": { "type": { "enum": [ "residential", "business" ] } }, "required": ["type"]}

additionalProperties 而失敗。「type」被視為額外的屬性。

資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business"}
不符合綱要

required 而失敗。「type」是必要的。

資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC"}
不符合綱要

因為 additionalProperties 只會識別在同一個子模式中宣告的屬性,所以它會將「street_address」、「city」和「state」以外的任何屬性視為額外的屬性。使用 allOf 組合模式並不會改變這一點。您可以使用的替代方法是將 additionalProperties 移至擴展模式,並重新宣告擴展模式中的屬性。

schema
{ "allOf": [ { "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } ],
"properties": { "street_address": true, "city": true, "state": true, "type": { "enum": [ "residential", "business" ] } }, "required": ["type"], "additionalProperties": false}
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business"}
符合 schema
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business", "something that doesn't belong": "hi!"}
不符合綱要

現在,additionalProperties 關鍵字能夠識別所有必要的屬性,並且模式可以如預期般運作。請繼續閱讀,以了解 unevaluatedProperties 關鍵字如何在不需要重新宣告屬性的情況下解決此問題。

未評估的屬性

2019-09 草案新增

在上一節中,我們看到了使用 additionalProperties 在使用組合「擴展」綱要時所面臨的挑戰。unevaluatedProperties 關鍵字與 additionalProperties 相似,不同之處在於它可以識別在子綱要中宣告的屬性。因此,前一節的範例可以被改寫,而無需重新宣告屬性。

schema
{ "allOf": [ { "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } ],
"properties": { "type": { "enum": ["residential", "business"] } }, "required": ["type"], "unevaluatedProperties": false}
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business"}
符合 schema
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business", "something that doesn't belong": "hi!"}
不符合綱要

unevaluatedProperties 的運作方式是收集在處理綱要時成功驗證的任何屬性,並將這些屬性用作允許的屬性列表。這讓您可以執行更複雜的操作,例如有條件地新增屬性。以下範例僅在地址的「type」為「business」時才允許「department」屬性。

schema
{ "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" }, "type": { "enum": ["residential", "business"] } }, "required": ["street_address", "city", "state", "type"],
"if": { "type": "object", "properties": { "type": { "const": "business" } }, "required": ["type"] }, "then": { "properties": { "department": { "type": "string" } } },
"unevaluatedProperties": false}
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "business", "department": "HR"}
符合 schema
資料
{ "street_address": "1600 Pennsylvania Avenue NW", "city": "Washington", "state": "DC", "type": "residential", "department": "HR"}
不符合綱要

在這個綱要中,只有當地址的「type」為「business」時,在 then 綱要中宣告的屬性才被視為「已評估」的屬性。

必要屬性

預設情況下,由 properties 關鍵字定義的屬性並非必要。但是,可以使用 required 關鍵字提供必要屬性的清單。

required 關鍵字接受一個包含零個或多個字串的陣列。這些字串中的每一個都必須是唯一的。

草案特定資訊
在 Draft 4 中,required 必須至少包含一個字串。

在以下定義使用者記錄的範例綱要中,我們要求每個使用者都必須有名稱和電子郵件地址,但如果他們沒有提供地址或電話號碼也沒關係。

schema
{ "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "address": { "type": "string" }, "telephone": { "type": "string" } }, "required": ["name", "email"]}
資料
{ "name": "William Shakespeare", "email": "[email protected]"}
符合 schema

提供額外的屬性是可以的,即使這些屬性未在架構中定義。

資料
{ "name": "William Shakespeare", "email": "[email protected]", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England", "authorship": "in question"}
符合 schema

缺少必要的 "email" 屬性會使 JSON 文件無效

資料
{ "name": "William Shakespeare", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England",}
不符合綱要

在 JSON 中,值為 null 的屬性並不等同於該屬性不存在。之所以會失敗,是因為 null 的類型不是 "string",而是 "null"

資料
{ "name": "William Shakespeare", "address": "Henley Street, Stratford-upon-Avon, Warwickshire, England", "email": null}
不符合綱要

屬性名稱

在草案 6 中新增

無論屬性的值為何,屬性的名稱都可以根據綱要進行驗證。如果您不想強制使用特定屬性,但又想確保這些屬性的名稱遵循特定慣例,這會很有用。例如,您可能想強制所有名稱都是有效的 ASCII 符號,以便它們可以在特定的程式語言中用作屬性。

schema
{ "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }}
資料
{ "_a_proper_token_001": "value"}
符合 schema
資料
{ "001 invalid": "value"}
不符合綱要

由於物件的鍵 (key) 必須始終是字串,因此給予 propertyNames 的綱要 (schema) 至少隱含以下條件:

schema
{ "type": "string" }

大小

可以使用 minPropertiesmaxProperties 關鍵字來限制物件的屬性數量。每個關鍵字都必須是非負整數。

schema
{ "type": "object", "minProperties": 2, "maxProperties": 3}
資料
{}
不符合綱要
資料
{ "a": 0 }
不符合綱要
資料
{ "a": 0, "b": 1 }
符合 schema
資料
{ "a": 0, "b": 1, "c": 2 }
符合 schema
資料
{ "a": 0, "b": 1, "c": 2, "d": 3 }
不符合綱要

需要協助嗎?

您覺得這些文件有幫助嗎?

幫助我們讓文件更完善!

在 JSON Schema,我們重視文件貢獻,如同其他類型的貢獻!

仍然需要協助嗎?

學習 JSON Schema 通常令人困惑,但別擔心,我們在這裡提供協助!