背景
随着 json 越来越广泛地被应用在各处,特别地,对于 json 的规范定义和校验也变得十分重要:
- 可以明确 json 中每个字段的含义、类型、约束条件之类的规则
- 减少团队开发之间的理解成本、后续维护成本、新人熟悉上手成本等
- 对于校验json提供天然的规则支持
可以理解为,json-schema 的出现,就是为了解决如何使用统一规则来定义和校验 json的。
定义
它是一套用于校验json的规范,让读写都同时遵循的一套规则。
json-schema之于json,就如同typescript(或flow)之于javascript
基本使用
基本概念
常用属性
-
maxLength: 最大长度限制
-
enum: 属性值的可用枚举值
-
minimum、exclusiveMinimum:大于等于、大于
-
maximum、exclusiveMaximum:小于等于、小于
-
pattern: 字符串约束支持正则表达式的描述
-
items: 规定数组的每一项;如果该属性是对象,就是properties
-
minItems: 至少必须xxx个元素以上
-
uniqueItems: 规定每个元素必须是唯一的(true/false)
例子
一个 json-schema 定义:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/person.schema.json",
"title": "Person",
"description": "it is a person object",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a person",
"type": "string"
},
"name": {
"description": "The identifier for a person",
"type": "string",
"maxLength": 50
},
"sex": {
"description": "The gender of the person",
"type": "string",
"enum": ["male", "female"]
},
"age": {
"description": "The age for a person",
"type": "number",
"exclusiveMinimum": 0,
"maximum": 1000
},
"phone": {
"description": "The contact for a person",
"type": "string",
"pattern": "^[13|14|15|16|17|18|19][0-9]{9}$"
},
"tags": {
"description": "The labels to describe a person",
"type": "array",
"items": [
{ "type": "string" }
],
"minItems": 1,
"uniqueItems": true
},
"address": {
"description": "The address for a person",
"type": "object",
"properties": {
"country": {
"type": "string"
},
"province": {
"type": "string"
},
"city": {
"type": "string"
},
"region": {
"type": "string"
},
"detail": {
"type": "string"
}
},
"required": ["country", province", "city", "region"]
},
},
"required": [ "id", "name" ]
}
符合上述 schema的 json:
{
"id": "A000000000",
"name": "溥仪",
"sex": "male",
"age": 112,
"phone": "1300000000",
"tags": ["吃饭","睡觉","发呆","末代皇帝"],
"address": {
"country": "天朝",
"province": "帝都",
"city": "帝都",
"region": "东城区",
"detail": "景山前街4号故宫博物馆",
}
}
进阶用法
复用
允许使用一些相同和类似的schema结构片段
使用 id、结构路径来进行复用
例子1:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"address": {
"type": "object",
"properties": {
"country": {
"type": "string"
},
"province": {
"type": "string"
},
"city": {
"type": "string"
},
"region": {
"type": "string"
},
"detail": {
"type": "string"
}
},
"required": ["country", province", "city", "region"]
},
},
"type": "object",
"properties": {
"receipt_address": {
"#ref": "#/definitions/address"
},
"send_address": {
"#ref": "#/definitions/address"
}
}
}
例子2:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"address": {
"$id": "#address",
"type": "object",
"properties": {
"country": {
"type": "string"
},
"province": {
"type": "string"
},
"city": {
"type": "string"
},
"region": {
"type": "string"
},
"detail": {
"type": "string"
}
},
"required": ["country", province", "city", "region"]
},
},
"type": "object",
"properties": {
"receipt_address": {
"#ref": "#address"
},
"send_address": {
"#ref": "#address"
}
}
}
递归
既然 可以通过 $ref 实现复用,那么复用自己(递归)也是可行的
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"element": {
"$id": "#element",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"props": {
"type": "object",
"properties": {},
},
"children": {
"type": "array",
"items": {"$ref": "#element"},
},
}
},
},
"type": "object",
"properties": {
"element": {
"#ref": "#element"
}
}
}
实际应用
{
"type": "object",
"properties": {
"aaa": {
"key": "aaa",
"name": "aaa",
"type": "string",
"title": "字段1",
"x-component": "input"
},
"bbb": {
"key": "bbb",
"name": "bbb",
"type": "number",
"title": "字段2",
"x-component": "numberpicker"
},
"ccc": {
"key": "ccc",
"name": "ccc",
"type": "date",
"title": "字段3",
"x-component": "datepicker"
}
}
}
上述 json-schema中,包含了 校验属性(type)和业务属性(x-component),不算严格意义上的标准schema,算是伪schema,但是大致思路和设计都是一致的。