文章目录
- 1. 写在最前面
- 2. Json schema 介绍
- 2.1 Json schema 是什么
- 2.2 使用 Json schema 的优势
- 2.3 Json schema 关键字说明
- 2.4 Json schema 常用的在线工具
- 3. 例子
- 3.1 使用上述关键字的 json shema
- 3.2 定义一个符合 schema 的 json
- 4. 使用 gojsonschema 的完成上述校验
- 4.1 目录结构定义
- 4.2 校验代码
- 4.3 试试错误的 json
- 5. 碎碎念
- 6. 参考资料
1. 写在最前面
笔者之前写过一篇关于 golang json validator 库 的介绍 ,该库对于 json 格式的校验是在其结构体定义的时候。但是此种方式在定义结构体字段比较多、比较复杂,或者结构体改动频繁的时候,使用不是很友好。
json validator 库使用需要在定义字段的时候增加 validate 的说明
type Person struct {
Name string `json:"name" validate:"required"`
Age int64 `json:"age" validate:"required"`
}
再介绍一个可以将 json 定义配置化的宝藏库,不足上面的使用缺点 ——https://github.com/xeipuuv/gojsonschema。
2. Json schema 介绍
2.1 Json schema 是什么
json-schema,是用 json 的格式来定义 json 结构的方法,可以通过 json-schema 的定义规则,来检查 json 结构是否符合预期。
2.2 使用 Json schema 的优势
- 可描述的 json 数据格式
- 提供清晰的人工和机器可读文档
- 完整的 json schema 结构定义,更有利于测试及快速验证 json 的合法性
2.3 Json schema 关键字说明
以下表格整理了常用的 json schema 的关键:
关键字 | 描述 |
$schema | 说明是哪个版本的 Json Schema,不同版本间不完全兼容 |
title | 用于进行简单的描述,可以省略 |
description | 用于进行详细的描述信息,可以省略 |
type | 用于约束 json 的字段类型、string、number\integer、object、array、boolean |
properties | 定义属性字段,定义每个字段的键和值类型 |
required | 必需属性,数组类型,指定上述 properties 中哪些是必需的字段 |
minimum | type 为 integer 时,可被接受的最小值 |
maximum | type 为 integer 时,可被接受的最大值 |
maxLength | type 为 string 或 array 时,可被接受的最小长度 |
minLength | type 为 string 或 array 时,可被接受的最大长度 |
uniqueItems | type 为 array 时,数组元素时否唯一 |
pattern | type 为 string 时,将字符串限制为特定的正则表达式 |
enum | 用于将值限制为一组固定的值,其至少含有一个元素,且所含元素必须唯一 |
additionalProperties | 将用于验证与 properties 不匹配的属性是否被允许 |
patternProperties | 将正则表达式映射到模式。如果属性名称与给定的正则表达式匹配,则属性值必须符合定义的类型 |
allOf | (AND) 必须对「所有」子模式有效 |
anyOf | (OR) 必须对「任意」子模式有效 |
oneOf | (XOR) 必须对「恰好一个」子模式有效 |
2.4 Json schema 常用的在线工具
- 根据 json 生成 schema — https://tooltt.com/json2schema/
- 校验 jsonschema 是否合法 — https://www.jsonschemavalidator.net/
- 校验某个 json 是否符合指定的 json schema 定义 — https://www.jsonschemavalidator.net/
3. 例子
3.1 使用上述关键字的 json shema
{
"$schema": "https://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"hobbies": {
"type": "array",
"minItems": 1,
"uniqueItems": true
},
"additionInformation":{
"oneOf": [
{
"type": "string",
"enum": ["xian", "shanghai"]
},
{
"type": "integer",
"minimum": 0,
"maximum":150
}
]
}
},
"patternProperties": {
"^Is.*": {
"type": "boolean"
}
},
"required": ["name","hobbies"],
"additionalProperties": false
}
3.2 定义一个符合 schema 的 json
根据上述 json schema 定义的 json 数据:
{
"name": "xiyan",
"hobbies": [
"coding"
],
"additionInformation": "xian"
}
json 在线校验的结果:
4. 使用 gojsonschema 的完成上述校验
4.1 目录结构定义
.
├── go.mod
├── go.sum
├── instance.json -> 待校验的 json 数据
├── main.go
└── schema.json -> json schema 的描述
4.2 校验代码
package main
import (
"fmt"
"github.com/xeipuuv/gojsonschema"
)
func main() {
schemaLoader := gojsonschema.NewReferenceLoader("file://./schema.json")
documentLoader := gojsonschema.NewReferenceLoader("file://./instance.json")
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
panic(err.Error())
}
if result.Valid() {
fmt.Printf("The document is valid\n")
} else {
fmt.Printf("The document is not valid. see errors :\n")
for _, desc := range result.Errors() {
fmt.Printf("- %s\n", desc)
}
}
}
4.3 试试错误的 json
把 additionInformation 的 value 赋值为一个布尔值再次校验:
{
"name": "xiyan",
"hobbies": [
"coding"
],
"additionInformation": false
}
输出:
jsonschema $> go run main.go
The document is not valid. see errors :
- additionInfomation: Must validate one and only one schema (oneOf)
- additionInfomation: additionInfomation must be one of the following: "xian", "shanghai"
5. 碎碎念
在大环境的阴霾笼罩下,最近的心情总是很难控制,会因为看到网络上的负面新闻难过,也会因为抢了一早上菜颗粒无收而伤心,但是日子总要过下去的,所以后面的日子请务必要加油吖:
- 热爱可抵岁月漫长,温柔可挡艰难时光。
- 总会有那么几个瞬间,让你忽然觉得,生活温柔且有趣。
- 会有沮丧失意的时候,但经常会跟自己讲,如果在这一件事情上运气不好,那一定会在别的什么事情上还回来,所以没什么好难过的,人要学会往前走,走下去,就总能看到更多更好的风景了。
6. 参考资料