JsonSchema学习笔记

一、什么是JsonSchema?

JsonSchema本质是一套规则,用来定义Json的数据格式。
例如定义人员信息,包含名字、年龄、生日。需要对这个人员信息的格式有约定,名字必须是字符串,年龄必须是整数,生日必须是日期类型的字符串。举例一个Json数据

{
    "name":"shoulinniao",
    "age":24,
    "birthday":"1998-11-11"
}

想要校验人员信息的JsonSchema可以是这么一个Json格式的规则

{
    "type":"object",
    "properties":{
        "name":{
            "type":"string"
        },
        "age":{
            "type":"integer"
        },
        "birthday":{
            "type":"string",
            "format":"date"
        }
    }
}

在线生成JsonSchema的工具:https://www.jsonschema.net/home
在线校验JsonSchema的工具:https://jsonschemalint.com/#!/version/draft-07/markup/json
JsonSchema版本有3个,draft-04、draft-06、draft-07
版本声明关键字$schema

{
    "$schema":"http://json-schema.org/draft-07/schema#"
}

二、类型关键字

定义一种数据结构首先从数据类型出发,例如学Java之初的八种基本数据类型。JsonSchema作为一套成熟的规则,也有自己的类型定义描述。
从上面的例子可以很容易看到"type"是定义类型的关键字,类型可以是"object","string","integer"。具体的数据类型有以下几种

  1. object 对象,可以包含多个字段
  2. string 字符串
  3. number 数字,包括浮点数和消暑
  4. integer 整数
  5. array 数组
  6. boolean 布尔,只有true和false两个合法值
  7. null 空,只有null一个合法值

三、类型额外特定参数

1.字符串string

  • minLength:最小长度
  • maxLength:最大长度
  • pattern:正则表达式
  • format:字符串格式,内容可以是date、time、data-time、email、hostname等
     {
         "type":"string",
         "minLength":11,
         "maxLength":100,
         "pattern":"^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$",
         "format":"date"
     }
    

2. 数值number和integer参数都相同

  • 满足某个数的倍数:multipleOf
  • 最小值:minimum
  • 最大值:maximum
  • 开区间最小值:exclusiveMinimum
  • 开区间最大值:exclusiveMaximum
{
    "type":"number",
    "multipleOf":5,
    "minimum":66,
    "maximum":99,
    "exclusiveMinimum":1234,
    "exclusiveMaximum":8888
}

这里显然区间最值与最大最小值矛盾,但这是合法的JsonSchema。
注意:这个例子如果用draft-04则会报错,其他两个版本则校验正常。

3. 布尔boolean和空值null类型没有额外的类型特定参数

4. 数组array

  • items:成员类型,对应值可以是一个JsonSchema,规定数组元素的JsonSchema,也可以是一个JsonSchema数组,要求数组元素按照JsonSchema数组的要求一一对应。
  • additionalItems:true/false,是否允许额外成员类型,仅当items是数组Schema才起作用,额外元素追加在数组后面。
  • minItems:数组元素最小个数
  • maxItems:数组元素最大个数
  • uniqueItems:true/false,数组元素是否唯一
  • contains:数组元素必须满足的schema样式
  • minContains:数组必须满足contains样式的最少元素个数
  • maxContains:数组必须满足contains样式的最多元素个数

例如以下Schema,定义了第一个元素必须是数值,第二个元素必须是字符串,允许追加其他元素在第二个元素后,并且元素个数必须大于等于2,小于等于54,元素值必须唯一的数组类型。

{
    "type":"array",
    "items":[
        {
            "type":"number"
        },
        {
            "type":"string"
        }
    ],
    "additionalItems":true,
    "minItems":2,
    "maxItems":54,
    "uniqueItems":true
   }

举例合适的Json数组 [1998,"shoulinniao",true]

5. 对象object

最常用的类型,Json格式一层套一层

  • properties:成员的schema,json格式,key是对象字段名,value是又一个schema
  • patternProperties:批量定义成员的schema,正则匹配多个key对应一种schema
  • required:必须出现的成员,数组格式
  • dependencies:成员依赖关系,json格式,key是字符串,value是字符串数组,表示key属性出现value数组里的所有属性不能缺席
  • additionalProperties:true/false,是否允许出现properties中没有定义的属性
  • minProperties:最少属性个数
  • maxProperties:最多属性个数

例如开头举例的人员信息可以用以下schema校验

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer"
    },
    "birthday": {
      "type": "string",
      "format": "date"
    }
  },
  "required": [
    "name"
  ],
  "dependencies": {
    "name": [
      "age",
      "birthday"
    ]
  }
}

四、逻辑组合

  • allOf:满足数组里所有的schema,数组格式
  • anyOf:满足任意多个schema,数组格式
  • oneOf:必须满足且仅满足其中一个schema,数组格式
  • not:不能满足not对应的schema,json格式

五、复杂结构

  • 定义:没有固定关键字,习惯在根节点的"definations"下定义可以多次引用的schema
  • $id:唯一标识定义中的属性,可以通过id引用,而不需要根节点下的完整路径
  • $ref:引用,路径以#开头代表根节点或者ID

schema和数据举例

{
  "definitions": {
    "bbox": {
      "$id": "bbox_schema",
      "type": "array",
      "item": {
        "type": "number"
      },
      "minLength": 4,
      "maxLength": 4
    }
  },
  "type": "object",
  "properties": {
    "plate_bbox": {
      "$ref": "#/definitions/bbox"
    },
    "table_bbox": {
      "$ref": "bbox_schema"
    }
  }
}
{
  "plate_bbox": [3,4,5,6],
  "table_bbox": [7,7,3,4]
}

六、通用关键字

enum:枚举数组,值必须选择其中一个,数组格式。
以下的仅用于描述,不影响校验效果

  • title:标题
  • description:描述
  • default:默认值
  • example:举例说明
  • "$comment":批注

七、Java代码运用

1.导入依赖包

<dependency>
	<groupId>com.github.erosb</groupId>
	<artifactId>everit-json-schema</artifactId>
	<version>1.14.0</version>
</dependency>

2.校验

        public static void main (String[]args){
            String json = "{\"plate_bbox\":[3,4,5,6],\"table_bbox\":[7,7,3,4]}";
            JSONObject jsonObject = new JSONObject(json);
            String jsonSchema = "{\"definitions\":{\"bbox\":{\"$id\":\"bbox_schema\",\"type\":\"array\",\"item\":{\"type\":\"number\"},\"minLength\":4,\"maxLength\":4}},\"type\":\"object\",\"properties\":{\"plate_bbox\":{\"$ref\":\"#/definitions/bbox\"},\"table_bbox\":{\"$ref\":\"bbox_schema\"}}}";
            JSONObject jsonSchemaObject = new JSONObject(jsonSchema);
            //两种方法确定版本
            // 1、在JsonSchema里把版本定义好了,否则默认加载4版本,如果加载6、7版本的特定内容会失败
            Schema schema = SchemaLoader.load(jsonSchemaObject);
            // 2、没有在JsonSchema里定义版本,声明加载器的版本
            SchemaLoader schemaLoader = SchemaLoader.builder().schemaJson(jsonSchemaObject).draftV7Support().build();
            schema = schemaLoader.load().build();
            // 校验
            schema.validate(jsonObject);
        }
posted @ 2022-03-06 20:40  守林鸟  阅读(593)  评论(0编辑  收藏  举报