當前位置:
首頁 > 知識 > json schema

json schema

json schema是用來驗證和描述json對象結構的。

在線驗證:https://www.jsonschemavalidator.net/

json schema 編輯器,推薦VSCode,寫上"$schema": "https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-07/schema.json#"後有自動補全。如下圖:

json schema


hello json schema world

舉例說明一下,比如一個不存在的交友網站的個人信息(名字性取向身高體重聯繫方式)json格式及其schema是下面這樣的:

{

"name": "張三",

"age": 25,

"sexualOrientation": "女",

"height_cm": 175,

"weight_kg": 65.1,

"contactInfo": {

"email": "zhangsan@gmail.com",

"phone": "13800000000"
}
}

{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"$comment": "嗯,不能小於14歲",
"type": "integer",
"minimum": 14,
"maximum": 100
},
"sexualOrientation": {
"type": "string",
"enum": [
"男",
"女",
"雙性戀"
]
},
"height_cm": {
"type": "integer"
},
"weight_kg": {
"type": "number"
},
"contactInfo": {
"type": "object",
"properties": {
"email": {
"type": "string",
"pattern": ".+@.+"
},
"phone": {
"type": "string",
"pattern": "\d{11}"
}
}
}
}
}

json schema本身也是一個json對象,在type欄位指定了類型,可以是"array", "boolean", "integer", "null", "number", "object", "string"。如果是object類型,那可以在properties裡面描述每一個欄位的類型。

type可以是一個數組,表示可以是多個類型。比如下面的json schema:

{
"type": [
"string",
"integer"
]
}
"string"

可以通過驗證,這是一個字元串3

可以通過驗證,這是一個整數1.5

不能通過驗證,這是一個浮點數{
}

不能通過驗證,這是一個object數組

如果type是array,name可以在items里描述數組元素的類型,items可以是一個對象也可以是一個數組。

比如下面這個schema,定義了一個對象,它有2個欄位array1和array2,array1的items是一個對象,array2的items是一個數組。

{
"type": "object",
"properties": {
"array1": {
"type": "array",
"items": {
"type": "number"
}
},
"array2": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "string"
}
]
}
}
}

有什麼區別了?items是數組那麼是分別定義每一個元素;items是對象的話表示定義所有元素。舉例說明一下:

{
"array1": [
1
],
"array2": [
1,
"2"
]
}

驗證通過,沒啥好解釋的{
"array1": [
1
],
"array2": [
1,
2
]
}

驗證失敗

schema里要求arry2的

第二個元素是字元串

但是2不是字元串

{
"array1": [
1,
2,
"3"
],
"array2": [
1,
"2"
]
}

驗證失敗

schema里array1的items是一個對象

這表示要求其所有的元素都是數字

"3"不是數字


json schema是「規則」

json schema定義的是「規則」,理解這一點很重要。

尤其是,如果你和我一樣先了解了xsd,先入為主的覺得XML Schema和json schema都是「schema」而且xml和json都是樹樁結構,於是覺得它們應該差不多,那就錯了。xsd是嚴格的面向對象設計思路,xsd定義的是對象,xml是xsd定義的對象的實例。而json schema只是規則,json對象和json schema之間的關係是json對象符合json schema定義的規則,或者,不符合。

理解這點對於理解後面的複雜一點的概念很重要。

並且,默認情況下,json schema只驗證出現了的內容(對象欄位或者數組元素)是否符合規則,而不驗證沒出現的。

舉例說明,對於如下的schema:

{
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
}
}
}
}
[]

空數組

符合規則

它沒有出現元素

沒出現的就不驗證

[
{
"field": "2"
}
]

也符合規則

沒啥好說的

[
{
"field": 2
}
]

驗證失敗,出現了field

但是類型錯誤

[
{
"field": "value"
},
{
}
]

也符合規則

數組中的第二個元素沒出現任何欄位

沒出現的不驗證

[
{
"field": "value"
},
{
},
{
"field1":"value"
}
]

還是符合規則

規則里沒要求field必須出現

同時沒對field1定義規則

所以這也是對的


復用:ref和definitions

如果把名字定義成姓和名,而一個人有名字,他有父母,父母也有名字。那姓名的規則定義就需要復用。

上例子:

{
"$schema": "https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-07/schema.json#",
"type": "object",
"properties": {
"name": {
"$ref": "#/definitions/Name"
},
"parents": {
"type": "object",
"properties": {
"father": {
"$ref": "#/definitions/Name"
},
"mother": {
"$ref": "#/definitions/Name"
}
}
}
},
"definitions": {
"Name": {
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
}
}
}
}

allOf,oneOf,anyOf

既然json schema是規則,那麼,就可以要求一個對象同時滿足多個規則,或者滿足多個規則之一。

allOf

allOf是一個數組,要求json對象必須滿足數組裡所有元素定義的規則。

舉例:為愛鼓掌一男一女,都有姓名年齡,不過女的年齡不得小於14歲,否則,去查查刑法。

{
"$schema": "https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-07/schema.json#",
"type": "object",
"properties": {
"male": {
"$ref": "#/definitions/Person"
},
"female": {
"allOf": [
{
"$ref": "#/definitions/Person"
},
{
"type": "object",
"properties": {
"age": {
"type": "integer",
"minimum": 14
}
},
"$comment": "注意這裡定義required欄位,age是必須出現的",
"required": [
"age"
]
}
]
}
},
"definitions": {
"Person": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
}
}
}
}

oneOf和anyOf的用法和allOf一致。含義,字面意思。

需要注意的是,oneOf是指其中一個,如果同時符合oneOf下面定義的多個規則,那是會驗證不過的。anyOf是任意一個或者多個。

比如下面這個很二的規則(實際上沒人會這麼定義)

{
"$schema": "https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-07/schema.json#",
"oneOf": [
{
"type": "integer",
"minimum": 14
},
{
"type": "integer",
"minimum": 20
}
]
}

用14去驗證,是通過的,滿足第一條,用20去驗證,是無法驗證通過的,因為20同時滿足了2條。


if,then,else

看名字就知道是幹啥的,不過這個if條件怎麼寫啊。再提一次,json schema定義的是規則。

if裡面不是我們常見的條件,而是規則,如果json對象滿足if下面定義的規則,那麼就用then下面的規則去驗證該json,否則就用else下面的規則去驗證。當然then以及else可不存在(這兩個要都不存在那寫if幹嘛啊)

不正經示例,如果心愛的女孩子單身狀態,那麼可以執行「聊騷」操作,如果有男朋友,那可以執行「挖牆腳操作」,如果已婚……那可以在「天涯何處無芳草」,「默默守護」操作中選一個,但是不能「當隔壁老王」。當然前提是知道女孩子狀態,所以girlState是required。

{
"$schema": "https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-07/schema.json#",
"type": "object",
"properties": {
"girlState": {
"type": "string",
"enum": [
"單身",
"有男朋友",
"已婚"
]
}
},
"allOf": [
{
"if": {
"type": "object",
"properties": {
"girlState": {
"const": "單身"
}
}
},
"then": {
"type": "object",
"properties": {
"action": {
"const": "聊騷"
}
}
}
},
{
"if": {
"type": "object",
"properties": {
"girlState": {
"const": "有男朋友"
}
}
},
"then": {
"type": "object",
"properties": {
"action": {
"const": "挖牆腳"
}
}
}
},
{
"if": {
"type": "object",
"properties": {
"girlState": {
"const": "已婚"
}
}
},
"then": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"天涯何處無芳草",
"默默守護"
]
}
}
}
},
{
"if": {
"type": "object",
"properties": {
"girlState": {
"const": "已婚"
}
}
},
"then": {
"not": {
"type": "object",
"properties": {
"action": {
"const": "當隔壁老王"
}
}
}
}
}
],
"required": [
"girlState"
]
}

可以思考一下為什麼用的是allOf

對於上面的schema

{
"girlState": "已婚",
"action": "當隔壁老王"
}

驗證失敗{
"girlState": "有男朋友",
"action": "挖牆腳"
}

驗證通過

雖然不道德

additionalItems和additionalProperties設置為false可以禁止未定義的元素/欄位出現。

不過additionalProperties設為false這個很不好用。

vscode有自動補全,其它的欄位看補全的名字就知道作用了。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

ul 下的li標籤都浮動,那麼ul的高度用兩個css搞定
django載入css文件和圖片

TAG:程序員小新人學習 |