专业的编程技术博客社区

网站首页 > 博客文章 正文

json schema(json schema生成工具)

baijin 2024-10-17 07:50:59 博客文章 4 ℃ 0 评论

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#"后有自动补全。如下图:

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有自动补全,其它的字段看补全的名字就知道作用了。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表