文章目录


  • 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 在线校验的结果:

golang json撖寡情 mysql golang json schema_golang

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. 参考资料