json Schema簡(jiǎn)介

什么是Json Schema??以一個(gè)例子來(lái)說(shuō)明

假設(shè)有一個(gè)web api,接受一個(gè)json請(qǐng)求,返回某個(gè)用戶在某個(gè)城市關(guān)系最近的若干個(gè)好友。一個(gè)請(qǐng)求的例子如下:

{

? ? "city" : "chicago",

? ?"number": 20,

? ? "user" : {

? ? ? ? "name":"Alex",

? ? ? ? "age":20? ? ? ? }

}

在上面的例子中,web api要求提供city,number,user三個(gè)成員,其中city是字符串,number是數(shù)值,user是一個(gè)對(duì)象,又包含了name和age兩個(gè)成員。

對(duì)于api來(lái)說(shuō),需要定義什么樣的請(qǐng)求合法,即什么樣的Json對(duì)于api來(lái)說(shuō)是合法的輸入。這個(gè)規(guī)范可以通過Json Schema來(lái)描述,對(duì)應(yīng)的Json Schema如下。

{

? ? "type": "object",

? ??"properties": {

?? ?? ? "city": { "type": "string" },

? ??? ??"number": { "type": "number" },

?? ??? ?"user": {

?? ??? ?? ? "type": "object",

? ??? ??? ? "properties": {

?? ??? ??? ?? ? "name" : {"type": "string"},

?? ??? ??? ??? ?"age" : {"type": "number"}

?? ??? ??? ?}?? ??? ??? ??? ??? ?? ?

?? ??? }

? ? }

}

例子可以通過Json Schema Validator來(lái)驗(yàn)證。

1.什么是Json Schema

Json Schema定義了一套詞匯和規(guī)則,這套詞匯和規(guī)則用來(lái)定義Json元數(shù)據(jù),且元數(shù)據(jù)也是通過Json數(shù)據(jù)形式表達(dá)的。Json元數(shù)據(jù)定義了Json數(shù)據(jù)需要滿足的規(guī)范,規(guī)范包括成員、結(jié)構(gòu)、類型、約束等。

本文后面的部分是簡(jiǎn)要介紹Json Schema定義的這些規(guī)則,以及如何用這些規(guī)則描述規(guī)范。

Json Schema定義了一系列關(guān)鍵字,元數(shù)據(jù)通過這些關(guān)鍵字來(lái)描述Json數(shù)據(jù)的規(guī)范。其中有些關(guān)鍵字是通用的;有些關(guān)鍵字是針對(duì)特定類型的;還有些關(guān)鍵字是描述型的,不影響合法性校驗(yàn)。本文的主要內(nèi)容就是介紹這些關(guān)鍵字的應(yīng)用。

2. 類型關(guān)鍵字

首先需要了解的是"type"關(guān)鍵字,這個(gè)關(guān)鍵字定義了Json數(shù)據(jù)需要滿足的類型要求。"type"關(guān)鍵字的用法如下面幾個(gè)例子:

{"type":"string"}。規(guī)定了Json數(shù)據(jù)必須是一個(gè)字符串,符合要求的數(shù)據(jù)可以是

"Today is a good day."

"I love you"

{"type" : "object"}。規(guī)定了Json數(shù)據(jù)必須是一個(gè)對(duì)象,符合要求的數(shù)據(jù)可以是

{"name" : "Alexander", "age" : 98}

{}

{"type" : "number"}。規(guī)定了Json數(shù)據(jù)必須是一個(gè)數(shù)值,符合要求的數(shù)據(jù)可以是。Java Script不區(qū)分整數(shù)、浮點(diǎn)數(shù),但是Json Schema可以區(qū)分。

2

0.5

{"type": "integer"}。要求數(shù)據(jù)必須是整數(shù)。

2

{"type" : "array"}。規(guī)定了Json數(shù)據(jù)必須是一個(gè)數(shù)組,符合要求的數(shù)據(jù)可以是

["abc", "cdf"]

[1, 2, 3]

["abc", 25, {"name": "Alexander"} ]

[]

{"type" : "boolean"}。這個(gè)Json Schema規(guī)定了Json數(shù)據(jù)必須是一個(gè)布爾,只有兩個(gè)合法值

true

false

{"type" : "null"}。null類型只有一個(gè)合法值

null

3. 簡(jiǎn)單類型

這部分介紹類型特定的關(guān)鍵,包括字符串、數(shù)值、布爾、空值幾種基本類型。

3.1 字符串

Json合法的字符串?? ?? ? ?? ?

"Today is a good day."

對(duì)應(yīng)的Json Schema

{"type": "string"}

可以進(jìn)一步對(duì)字符串做規(guī)范要求。字符串長(zhǎng)度匹配正則表達(dá)式、字符串格式。

3.1.1 字符串長(zhǎng)度

關(guān)鍵字: minLength, maxLength

可以對(duì)字符串的最小長(zhǎng)度、最大長(zhǎng)度做規(guī)范。

{

? ? "type" : "string",

? ? "minLength" : 2,

? ? "maxLength" : 3,

}

3.1.2 正則表達(dá)式

關(guān)鍵字: pattern

可以對(duì)字符串應(yīng)滿足的Pattern做規(guī)范,Pattern通過正則表達(dá)式描述。

3.1.3 字符串Format

關(guān)鍵字: format

可以通過Json Schema內(nèi)建的一些類型,對(duì)字符串的格式做規(guī)范,例如電子郵件、日期、域名等。

{ "type" : "string", "format" : "date", }

Json Schema支持的format包括"date", "time", "date-time", "email", "hostname"等。具體可以參考文檔。

3.2 數(shù)值

Json Schema數(shù)值類型包括"number"和"integer"。number合法的數(shù)值可以是

2

0.1

對(duì)應(yīng)的Json Schema為

{"type": "number"}

如果是integer則只能是整數(shù)。"number"和"integer"的類型特定參數(shù)相同,可以限制倍數(shù)、范圍

3.2.1 數(shù)值滿足倍數(shù)

關(guān)鍵字: multipleOf

可以要求數(shù)值必須某個(gè)特定值的整數(shù)倍。例如要求數(shù)值必須是10的整數(shù)倍。

{

? ? "type" : "number",

? ? "multipleOf" : 10,

}

3.2.2 數(shù)值范圍

關(guān)鍵字: minimum, maximum, exclusiveMinimum, exclusiveMaximum

可以限制數(shù)值的方位,包括最大值、最小值、開區(qū)間最大值、開區(qū)間最小值。

要求數(shù)值在[0, 100)范圍內(nèi)。

{

? ? "type" : "number",

? ? "minimum": 0,

? ? "exclusiveMaximum": 100

}

3.3 布爾

布爾類型沒有額外的類型特定參數(shù)。

3.4 空值

null類型沒有額外的類型特定參數(shù)。

4. 復(fù)合類型

復(fù)合類型可以通過Nest的方式構(gòu)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。包括數(shù)組、對(duì)象。

4.1 數(shù)組

Json數(shù)組合法數(shù)據(jù)的例子

[1, 2, 3]

[1, "abc", {"name" : "alex"}]

[]

Json Schema為

{"type": "array"}

數(shù)組的類型特定參數(shù),可以用來(lái)限制成員類型、是否允許額外成員最小元素個(gè)數(shù)、最大元素個(gè)數(shù)是否允許元素重復(fù)。

4.1.1 數(shù)組成員類型

關(guān)鍵字: items

可以要求數(shù)組內(nèi)每個(gè)成員都是某種類型,通過關(guān)鍵字items實(shí)現(xiàn)。下面的Schema要求數(shù)組內(nèi)所有元素都是數(shù)值,這時(shí)關(guān)鍵字"items"對(duì)應(yīng)一個(gè)嵌套的Json Schema,這個(gè)Json Schema定義了每個(gè)元素應(yīng)該滿足的規(guī)范。

{

? ? "type": "array",

? ? "items": {

? ? ? ? "type": "number"? ? }

}

[1, 2, 3]

關(guān)鍵字items還可以對(duì)應(yīng)一個(gè)數(shù)組,這時(shí)Json數(shù)組內(nèi)的元素必須與Json Schema內(nèi)items數(shù)組內(nèi)的每個(gè)Schema按位置一一匹配。

{

? ? "type": "array",

? ? "items": [

? ? {

? ? ? ? "type": "number"? ? },

? ? {

? ? ? ? "type": "string"? ? }]

}

[1, "abc"]

4.1.2 數(shù)組是否允許額外成員

關(guān)鍵字: additionalItems

當(dāng)使用了items關(guān)鍵字,并且items關(guān)鍵字對(duì)應(yīng)的是Schema數(shù)組,這個(gè)限制才起作用。關(guān)鍵字additionalItems規(guī)定Json數(shù)組內(nèi)的元素,除了一一匹配items數(shù)組內(nèi)的Schema外,是否還允許多余的元組。當(dāng)additionalItems為true時(shí),允許額外元素。

{

? ? "type": "array",

? ? "items": [

? ? {

? ? ? ? "type": "number"? ? },

? ? {

? ? ? ? "type": "string"? ? }],

? ? "additionalItems" : true

}

[1, "abc", "x"]

4.1.3 數(shù)組元素個(gè)數(shù)

關(guān)鍵字: minItems, maxItems

可以限制數(shù)組內(nèi)元素的個(gè)數(shù)。

{

? ? "type": "array",

? ? "items": {

? ? ? ? "type": "number"? ? },

? ? "minItems" : 5,

? ? "maxItems" : 10

}

[1,2,3,4,5,6]

4.1.4 數(shù)組內(nèi)元素是否必須唯一

關(guān)鍵字: uniqueItems

規(guī)定數(shù)組內(nèi)的元素是否必須唯一。

{

? ? "type": "array",

? ? "items": {

? ? ? ? "type": "number"? ? },

? ? "uniqueItems" : true

}

[1,2,3,4,5]

4.2 對(duì)象

Json對(duì)象是最常見的Json數(shù)據(jù)類型,合法的數(shù)據(jù)可以是

{

? ? "name": "Froid",

? ? "age" : 26,

? ? "address" : {

? ? ? ? "city" : "New York",

? ? ? ? "country" : "USA"? ? }

}

就對(duì)象類型而言,最基本的類型限制Schema是

{"type" : "object"}

然而,除了類型外,我們通常需要對(duì)其成員做進(jìn)一步約定。對(duì)象的類型特定關(guān)鍵字,大多是為此目的服務(wù)的。

4.2.1 成員的Schema

關(guān)鍵字:properties

規(guī)定對(duì)象各成原所應(yīng)遵循的Schema。

{

? ? "type": "object", ? ??

? ? "properties": { ?? ?

? ? ? ? "name": {"type" : "string"},

? ? ? ? "age" : {"type" : "integer"},

? ? ? ? "address" : {

? ? ? ? ? ? "type" : "object",

? ? ? ? ? ? "properties" : {

? ? ? ? ? ? ? ? "city" : {"type" : "string"},

? ? ? ? ? ? ? ? "country" : {"type" : "string"}

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

對(duì)于上例中的Schema,合法的data是

{

? ? "name": "Froid",

? ? "age" : 26,

? ? "address" : {

? ? ? ? "city" : "New York",

? ? ? ? "country" : "USA"? ? }

}

properties關(guān)鍵字的內(nèi)容是一個(gè)key/value結(jié)構(gòu)的字典,其key對(duì)應(yīng)Json數(shù)據(jù)中的key,其value是一個(gè)嵌套的Json Schema。表示Json數(shù)據(jù)中key對(duì)應(yīng)的值所應(yīng)遵守的Json Schema。在上面的例子中,"name"對(duì)應(yīng)的Schema是{"type" : "string"},表示"name"的值必須是一個(gè)字符串。在Json數(shù)據(jù)中,對(duì)象可以嵌套,同樣在Json Schema中也可以嵌套。如"address"字段,在Json Schema中它的內(nèi)容是一個(gè)嵌套的object類型的Json Schema。

4.2.2 批量定義成員Schema

關(guān)鍵字:patternProperties

與properties一樣,但是key通過正則表達(dá)式匹配屬性名。

{

? ? "type": "object",

? ? "patternProperties": {

? ? ? ? "^S_": { "type": "string" },

? ? ? ? "^I_": { "type": "integer" }

? ? }

}

{"S_1" : "abc"}

{"S_1" : "abc", "I_3" : 1}

4.2.3 必須出現(xiàn)的成員

關(guān)鍵字:required

規(guī)定哪些對(duì)象成員是必須的。

{

? ? "type": "object", ? ??

? ? "properties": { ?? ?

? ? ? ? "name": {"type" : "string"},

? ? ? ? "age" : {"type" : "integer"},

? ? },

? ? "required" : ["name"]

}

上例中"name"成員是必須的,因此合法的數(shù)據(jù)可以是

{"name" : "mary", "age" : 26}

{"name" : "mary"}

但缺少"name"則是非法的

{"age" : 26}

4.2.4 成員依賴關(guān)系

關(guān)鍵字:dependencies

規(guī)定某些成員的依賴成員,不能在依賴成員缺席的情況下單獨(dú)出現(xiàn),屬于數(shù)據(jù)完整性方面的約束。

{

? ? "type": "object",

? ? "dependencies": {

? ? ? ? "credit_card": ["billing_address"]

? ? }

}

dependencies也是一個(gè)字典結(jié)構(gòu),key是Json數(shù)據(jù)的屬性名,value是一個(gè)數(shù)組,數(shù)組內(nèi)也是Json數(shù)據(jù)的屬性名,表示key必須依賴的其他屬性。

上面Json Schema合法的數(shù)據(jù)可以是

{}

{"billing_address" : "abc"}

但如果有"credit_card"屬性,則"billing_address" 屬性不能缺席。下面的數(shù)據(jù)是非法的

{"credit_card": "7389301761239089"}

4.2.5 是否允許額外屬性

關(guān)鍵字:additionaProperties

規(guī)定object類型是否允許出現(xiàn)不在properties中規(guī)定的屬性,只能取true/false。

{

? ? "type": "object", ? ??

? ? "properties": { ?? ?

? ? ? ? "name": {"type" : "string"},

? ? ? ? "age" : {"type" : "integer"},

? ? },

? ? "required" : ["name"],

? ? "additionalProperties" : false

}

上例中規(guī)定對(duì)象不能有"name"和"age"之外的成員。合法的數(shù)據(jù)

{"name" : "mary"}

{"name" : "mary", "age" : 26}

非法的數(shù)據(jù)

{"name" : "mary", "phone" : ""84893948}

4.2.6 屬性個(gè)數(shù)的限制

關(guān)鍵字:minProperties, maxProperties

規(guī)定最少、最多有幾個(gè)屬性成員。

{

? ? "type": "object",

? ? "minProperties": 2,

? ? "maxProperties": 3

}

{"name" : "mary", "age" : 26}

{"name" : "mary", "age" : 26, "phone" : "37839233"}

5. 邏輯組合

關(guān)鍵字:allOf, anyOf, oneOf, not

從關(guān)鍵字名字可以看出其含義,滿足所有、滿足任意、滿足一個(gè)。前三個(gè)關(guān)鍵字的使用形式是一致的,以allOf為例說(shuō)明其形式。

{

? ? "allOf" : [

? ? ? ? Schema1,

? ? ? ? Schema2,

? ? ? ? ...

? ? ]

}

其中,"allOf"的內(nèi)容是一個(gè)數(shù)組,數(shù)組內(nèi)的成員都是內(nèi)嵌的Json Schema。上例Schema1、Schema2都是內(nèi)嵌的Json Schema。整個(gè)Schema表示當(dāng)前Json數(shù)據(jù),需要同時(shí)滿足Schema1、Schema2,。

5.1 allOf

滿足allOf數(shù)組中的所有Json Schema。

{

? ? "allOf" : [

? ? ? ? Schema1,

? ? ? ? Schema2,

? ? ? ? ...

? ? ]

}

需要注意,不論在內(nèi)嵌的Schema里還是外部的Schema里,都不應(yīng)該使"additionalProperties"為false。否則可能會(huì)生成任何數(shù)據(jù)都無(wú)法滿足的矛盾Schema。

可以用來(lái)實(shí)現(xiàn)類似“繼承”的關(guān)系,例如我們定義了一個(gè)Schema_base,如果想要對(duì)其進(jìn)行進(jìn)一步修飾,可以這樣來(lái)實(shí)現(xiàn)。

{

? ? "allOf" : [

? ? ? ? Schema_base

? ? ]

? ? "properties" : {

? ? ? ? "other_pro1" : {"type" : "string"},

? ? ? ? "other_pro2" : {"type" : "string"}

? ? },

? ? "required" : ["other_pro1", "other_pro2"]

}

Json數(shù)據(jù)既需要滿足Schema_base,又要具備屬性"other_pro1"、"other_pro2"。

5.2 anyOf

滿足anyOf數(shù)組中的任意個(gè)Schema。

{

? ? "anyOf" : [

? ? ? ? Schema1,

? ? ? ? Schema2,

? ? ? ? ...

? ? ]

}

Json數(shù)據(jù)需要滿足Schema1、Schema2中的一個(gè)或多個(gè)。

5.3 oneOf

滿足且進(jìn)滿足oneOf數(shù)組中的一個(gè)Schema,這也是與anyOf的區(qū)別。

{

? ? "oneOf" : [

? ? ? ? Schema1,

? ? ? ? Schema2,

? ? ? ? ...

? ? ]

}

5.4 not

這個(gè)關(guān)鍵字不嚴(yán)格規(guī)定Json數(shù)據(jù)應(yīng)滿足什么要求,它告訴Json不能滿足not所對(duì)應(yīng)的Schema。

{

? ? "not" : {"type" : "string"}

}

只要不是string類型的都Json數(shù)據(jù)都可以。

6. 復(fù)雜結(jié)構(gòu)

對(duì)復(fù)雜結(jié)構(gòu)的支持包括定義和引用??梢詫⑾嗤慕Y(jié)構(gòu)定義成一個(gè)“類型”,需要使用該“類型”時(shí),可以通過其路徑或id來(lái)引用。

6.1 定義

關(guān)鍵字:無(wú)

定義一個(gè)類型,并不需要特殊的關(guān)鍵字。通常的習(xí)慣是在root節(jié)點(diǎn)的definations下面,定義需要多次引用的schema。definations是一個(gè)json對(duì)象,key是想要定義的“類型”的名稱,value是一個(gè)json schema。

{

? ? "definitions": {

? ? ? ? "address": {

? ? ? ? ? ? "type": "object",

? ? ? ? ? ? "properties": {

? ? ? ? ? ? ? ? "street_address": { "type": "string" },

? ? ? ? ? ? ? ? "city":? ? ? ? ? { "type": "string" },

? ? ? ? ? ? ? ? "state":? ? ? ? ? { "type": "string" }

? ? ? ? ? ? },

? ? ? ? ? ? "required": ["street_address", "city", "state"]

? ? ? ? }

? ? },

? ? "type": "object",

? ? "properties": {

? ? ? ? "billing_address": { "$ref": "#/definitions/address" },

? ? ? ? "shipping_address": { "$ref": "#/definitions/address" }

? ? }

}

上例中定義了一個(gè)address的schema,并且在兩個(gè)地方引用了它,#/definitions/address表示從根節(jié)點(diǎn)開始的路徑。

6.2?id>??關(guān)鍵字:id>??關(guān)鍵字:id**

可以在上面的定義中加入id屬性,這樣可以通過id屬性,這樣可以通過id屬性的值對(duì)該schema進(jìn)行引用,而不需要完整的路徑。

... "address": {

? ? ? ? ? ? "type": "object",

? ? ? ? ? ? "$id" : "address",

? ? ? ? ? ? "properties": {

? ? ? ? ? ? ? ? "street_address": { "type": "string" },

? ? ? ? ? ? ? ? "city":? ? ? ? ? { "type": "string" },

? ? ? ? ? ? ? ? "state":? ? ? ? ? { "type": "string" }

? ? ? ? ? ? },

? ? ? ? ? ? "required": ["street_address", "city", "state"]

? ? ? ? }

...

6.3 引用

關(guān)鍵字:$ref

關(guān)鍵字$ref可以用在任何需要使用json schema的地方。如上例中,billing_address的value應(yīng)該是一個(gè)json schema,通過一個(gè)$ref替代了。

$ref的value,是該schema的定義在json中的路徑,以#開頭代表根節(jié)點(diǎn)。

{

? ? "properties": {

? ? ? ? "billing_address": { "$ref": "#/definitions/address" },

? ? ? ? "shipping_address": { "$ref": "#/definitions/address" }

? ? }

}

如果schema定義了$id屬性,也可以通過該屬性的值進(jìn)行引用。

{

? ? "properties": {

? ? ? ? "billing_address": { "$ref": "#address" },

? ? ? ? "shipping_address": { "$ref": "#address" }

? ? }

}

7. 通用關(guān)鍵字

通用關(guān)鍵字可以在任何json schema中出現(xiàn),有些影響合法性校驗(yàn),有些只是描述作用,不影響合法性校驗(yàn)。

7.1 enum

關(guān)鍵字:enum

可以在任何json schema中出現(xiàn),其value是一個(gè)list,表示json數(shù)據(jù)的取值只能是list中的某個(gè)。

{

? ? "type": "string",

? ? "enum": ["red", "amber", "green"]

}

上例的schema規(guī)定數(shù)據(jù)只能是一個(gè)string,且只能是"red"、"amber"、"green"之一。

7.2 metadata

關(guān)鍵字:title,description,default,example

只作為描述作用,不影響對(duì)數(shù)據(jù)的校驗(yàn)。

{

? ? "title" : "Match anything",

? ? "description" : "This is a schema that matches anything.",

? ? "default" : "Default value",

? ? "examples" : [

? ? ? ? "Anything",

? ? ? ? 4035? ? ]

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容