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