JSON Schema入門和應(yīng)用
何為JSON Schema?
JSON數(shù)據(jù)格式對于web開發(fā)者都為所熟悉,在平時的開發(fā)中離不開它,例如前后端數(shù)據(jù)傳輸格式,webpack配置文件,對象序列化等實(shí)際應(yīng)用場景,通常都以JSON格式定義和儲存。它以簡潔易懂的結(jié)構(gòu)、體積小的優(yōu)點(diǎn)得以在各類編程語言中廣泛流行。
那么什么是JSON Schema?
JSON Schema其實(shí)是對json數(shù)據(jù)格式的描述和規(guī)范,是對JSON格式一種約束,更明確地定義數(shù)據(jù)的類型和結(jié)構(gòu)。伴隨著JSON被創(chuàng)造出來,JSON Schema的誕生是必然的,類似其他數(shù)據(jù)格式Y(jié)AML,也會創(chuàng)造YAML Schema的標(biāo)準(zhǔn)來進(jìn)行規(guī)范,并使用這個規(guī)范來校驗(yàn)格式。這就好比有了Javascript,自然就會有Typescript,開發(fā)者更傾向于使用工具替代人為來進(jìn)行約束,校驗(yàn),使開發(fā)效率和開發(fā)質(zhì)量大大加強(qiáng)。
掌握使用
舉個簡單的例子,你便清楚JSON Schema的使用
這里有兩個對象a,b,唯一的區(qū)別是對象里的屬性類型不同,當(dāng)你想指定對象屬性的類型時,假若你只想要字符串類型,那么可以使用JSON Schema來進(jìn)行定義
json
代碼解讀
復(fù)制代碼{
"type": "object",
"properties": {
"title": {
"type": "string"
}
}
}
js
代碼解讀
復(fù)制代碼// right
var a = {
title: '123'
}
// error
var b = {
title: 123
}
上面是最簡潔的JSON Schema對象定義,從中我們可以得知定義的變量類型是對象,而這個變量對象里具有title屬性,title屬性的類型是string類型。好了,到這里你已經(jīng)掌握了JSON Schema使用,是不是好簡單??。
當(dāng)然,JSON Schema既然是一套標(biāo)準(zhǔn)和規(guī)范,那么就會有好多語義需要理解,下面說說常見用法
數(shù)據(jù)類型
在JSON Schema中使用最多的是type
關(guān)鍵字,它包含了JSON格式的基本類型
類型 | 描述 |
---|---|
string | 字符串型,雙引號包裹的 Unicode 字符和反斜杠轉(zhuǎn)義字符 |
number | 數(shù)字型,包括整型(int)和浮點(diǎn)數(shù)型(float) |
boolean | 布爾型,true 或 false |
object | 對象型,無序的鍵:值對集合 |
array | 數(shù)組型,有序的值序列 |
null | 空型 |
關(guān)鍵字
以O(shè)bject類型為例,列舉在JSON Schma所經(jīng)常用到的關(guān)鍵字
示例:
json
代碼解讀
復(fù)制代碼{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/schemas/person",
"title": "base info",
"description": "base information about person",
"type": "object",
"required": ["name", "age", "phone"],
"definitions": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 10
}
},
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 10
},
"age": {
"type": "number",
"minimum": 18,
"exclusiveMinimum": true,
"maximum": 65,
"exclusiveMaximum": true
},
"phone": {
"type": "string",
"pattern": "^1\\d{10}$"
},
"parents": {
"type": "array",
"items": [{ "$ref": "#/definitions/name" }],
"minItems": 1,
"maxItems": 2,
"uniqueItems": true
},
"address": {
"type": "object",
"properties": {
"city": {
"type": "string",
"enum": ["guangzhou", "beijing"]
}
}
}
}
}
關(guān)鍵字 | 描述 |
---|---|
$schema | 聲明此json片段屬于JSON Schema,并遵循所聲明的JSON Schema版本規(guī)范 |
$id | 為JSON Schema聲明一個統(tǒng)一資源標(biāo)識符,使解析$ref時能夠引用片段 |
title | 為JSON Schema文件提供標(biāo)題 |
description | 為JSON Schema文件提供描述信息 |
definitions | 聲明子schema,使解析$ref能夠引用片段 |
$ref | 引用JSON Schema片段 |
required | 定義對象類型properties所聲明的字段是否必須,值必須是數(shù)組,數(shù)組中的元素必須是字符串類型且唯一 |
type | 定義元素的類型 |
properties | 定義對象類型里的屬性(鍵值對),每個字段的值都是一個有效的schema片段,用來限制每個字段的格式 |
minimum | 約束取值范圍,標(biāo)識取值范圍應(yīng)該大于或等于minimum |
exclusiveMinimum | 假若minimum或exclusiveMinimum同時存在,且exclusiveMinimum為true,則取值范圍大于minimum |
maximum | 約束取值范圍,標(biāo)識取值范圍應(yīng)該小于或等于maximum |
exclusiveMaximum | 假若maximum或exclusiveMaximum同時存在,且exclusiveMaximum為true,則取值范圍小于maximum |
minLength | 字符串類型數(shù)據(jù)的最小長度 |
maxLength | 字符串類型數(shù)據(jù)的最大長度 |
pattern | 使用正則表達(dá)式約束字符串類型數(shù)據(jù) |
items | 用來定義數(shù)組類型的子元素,值必須為數(shù)組,且是一個有效的schema片段 |
minItems | 定義數(shù)組類型大小的最小長度 |
maxItems | 定義數(shù)組類型大小的最大長度 |
uniqueItems | 定義數(shù)組類型子元素是否必須唯一 |
enum | 用來限制值的范圍,值必須在enum所指定的集合里面 |
以上是比較常用到的關(guān)鍵字,還有一些其他的關(guān)鍵字可以閱讀官方文檔進(jìn)行深入地了解和使用
進(jìn)階使用:
正則屬性
提供patternProperties
關(guān)鍵字,對屬性字段名提供正則校驗(yàn)
json
代碼解讀
復(fù)制代碼{
"type": "object",
"patternProperties": {
"^S_": { "type": "string" },
"^I_": { "type": "integer" }
}
}
sh
代碼解讀
復(fù)制代碼// right
"{ "S_25": "This is a string" }"
// right
{ "I_0": 42 }
sh
代碼解讀
復(fù)制代碼// error S_開頭的字段名的值必須為字符串類型
{ "S_0": 42 }
// error I_開頭的字段名的值必須為數(shù)值類型
{ "I_42": "This is a string" }
組合sechma
JSON Sechma提供一些關(guān)鍵字來講多個子schema片段組合在一起,類似布爾算符AND, OR, XOR, 和 NOT,通過布爾邏輯來驗(yàn)證
關(guān)鍵字 | 描述 |
---|---|
allOf | 相當(dāng)于AND布爾算符,必須滿足所有的子schema校驗(yàn) |
anyOf | 相當(dāng)于OR布爾算符,必須滿足任意子schema校驗(yàn) |
oneOf | 相當(dāng)于XOR布爾算符,必須滿足其中一個子schema校驗(yàn) |
not | 相當(dāng)于NOT布爾算符,必須都不滿足所有的子schema校驗(yàn) |
以allOf
關(guān)鍵字為例:
必須要滿足符合字符串類型且最大長度為5的值
json
代碼解讀
復(fù)制代碼{
"allOf": [
{ "type": "string" },
{ "maxLength": 5 }
]
}
sh
代碼解讀
復(fù)制代碼// right
"short"
sh
代碼解讀
復(fù)制代碼// error 字符長度超出5
"too long"
條件sechma
可以使用if
,then
,else
關(guān)鍵字實(shí)現(xiàn)條件邏輯判斷,當(dāng)符合if
子schema條件,則對then
的子schema條件進(jìn)行校驗(yàn),若if
子schema條件不通過,則走else
子schema條件校驗(yàn)
json
代碼解讀
復(fù)制代碼{
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"country": {
"default": "United States of America",
"enum": ["United States of America", "Canada"]
}
},
"if": {
"properties": { "country": { "const": "United States of America" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
},
"else": {
"properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
}
}
sh
代碼解讀
復(fù)制代碼// right
// if的schema驗(yàn)證通過,則校驗(yàn)then的schema,20500 符合 /[0-9]{5}(-[0-9]{4})?/ 正則表達(dá)式
{
"street_address": "1600 Pennsylvania Avenue NW",
"country": "United States of America",
"postal_code": "20500"
}
sh
代碼解讀
復(fù)制代碼// error
// if的schema驗(yàn)證不通過,則校驗(yàn)else的schema,10000 不符合 /[A-Z][0-9][A-Z] [0-9][A-Z][0-9]/ 正則表達(dá)式
{
"street_address": "24 Sussex Drive",
"country": "Canada",
"postal_code": "10000"
}
遞歸
使用$ref
關(guān)鍵字引用自己的子schema片段,實(shí)現(xiàn)遞歸模式,可以用于樹形結(jié)構(gòu)的描述
json
代碼解讀
復(fù)制代碼{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "$ref遞歸調(diào)用",
"definitions": {
"node": {
"type": "object",
"properties": {
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/node"
}
}
}
}
},
"type": "object",
"properties": {
"tree": {
"$ref": "#/definitions/node"
}
}
}
以下的JSON結(jié)構(gòu)才能在上述的JSON Schema校驗(yàn)通過
json
代碼解讀
復(fù)制代碼{
"tree": {
"children": [
{
"children": [
{
"children": []
}
]
}
]
}
}
應(yīng)用
JSON Schema規(guī)范了JSON格式,使JSON的解析控制在一定的范圍了,在JSON輸入到輸出等過程中添加Schema協(xié)議的校驗(yàn),減少了代碼程序出錯的幾率,一定程度上保證了代碼的質(zhì)量。
JSON Schema在公司的內(nèi)部項(xiàng)目上也有應(yīng)用,例如raptor活動運(yùn)營平臺JSON Schema可視化組件編輯器,pear配置管理平臺使用JSON Schema生成輸入表單,在amis開發(fā)中通過json配置中臺頁面等等??梢姡琂SON Schema在代碼開發(fā)過程中發(fā)揮不可忽視的作用,我們應(yīng)該加以理解并應(yīng)用JSON Schema,下面歸納一下JSON Schema一些用途。
1、生成JSON格式可讀文檔
使用過typescript都應(yīng)該了解靜態(tài)類型的好處,代碼包含了類型接口聲明,相當(dāng)于文檔注釋,使代碼一目了然,提高了可讀性。我們可以基于現(xiàn)有的JSON來生成JSON Schema,快速生成JSON格式規(guī)范,相當(dāng)于一份可讀文檔,減少了團(tuán)隊(duì)之間的溝通理解成本。
通過JSON轉(zhuǎn)換JSON Schema在線工具:
www.jsonschema.net/
2、提供更為準(zhǔn)確可靠的mock數(shù)據(jù)
基于JSON Schema提供多種校驗(yàn)約束條件,可以使用它原生的能力來生成更為準(zhǔn)確可靠的mock數(shù)據(jù)
使用JSON Schema生成mock數(shù)據(jù)在線工具:
json-schema-faker.js.org/
3、數(shù)據(jù)校驗(yàn)
基于JSON Schema提供多種校驗(yàn)約束條件,可以定義數(shù)據(jù)的校驗(yàn)規(guī)則,通過JSON Schema進(jìn)行數(shù)據(jù)校驗(yàn),多用于接口請求參數(shù)校驗(yàn),表單校驗(yàn),和數(shù)據(jù)校驗(yàn)自動化測試上
JSON Schema校驗(yàn)工具:Ajv
4、基于JSON Schema配置文件渲染UI組件
借助vue、react框架組件化理念以及動態(tài)渲染組件能力,涌現(xiàn)了許多基于JSON Schema配置文件渲染表單或者組件的庫,有效解決通用性組件大量重復(fù)使用的場景。通過JSON配置組件乃至頁面,能夠使代碼轉(zhuǎn)化為文件,使數(shù)據(jù)得以導(dǎo)入導(dǎo)出,便于遷移儲存。另外也可以開發(fā)可視化編輯器,通過拖拽交互,生成JSON文件,降低開發(fā)使用難度?;谶@一系列的方案,使開發(fā)效率大大提升和降低后續(xù)的代碼維護(hù)。
在vue框架下,vue-json-schema-form提供了表單組件生成工具
vue-json-schema-form 基于JSON Schema的關(guān)鍵字type
所定義的類型來渲染對應(yīng)表單組件,并適配了第三方的UI庫
主要架構(gòu):
渲染流程:
參考資料: