json Schema 数据校验工具

JSON Schema官网

1:JSON Schema简介

学习json schema基础
和XML Schema用来验证xml数据结构一样,jsonSchema是验证JSONdata数据结构的强大工具。
如果不会写有自动生成工具:https://www.jsonschema.net/login

1.1:基础知识

在JSON模式中,空对象和true都是完全有效的模式,可以接受任何有效的JSON。

  • a.json文件
{ }          或者true

1.2:定义关键字解释

架构关键字:$schema and $id.
	$schema该关键字用于指定JSON Schema版本信息
	Id是唯一标识产品的数值。因为这是产品的规范标识符,所以它是必需的。
模式注释:title and description. 
	用来进行注释的,描述文件或者字段
验证关键字:type。
	定义数据的类型,定义后只支持该特定类型
属性关键字:properties
	定义该json的属性部分

demo

{
  "id":"this is json id .",
  "description":"this is test json schema .",
  "properties":{
    "name":{
      "type":"string",
      "description":"people name ."
    }
  }
}
1:$schema

用于指定版本信息:可在此查看schema版本
共有4;6;7等多个版本,比如6版本

"$schema": "http://json-schema.org/draft-06/schema#",

2:type支持数据类型

string
number
integer
object
array
boolean
null

2.1:string字符串

支持对字符串的长度,正则表达式。对于其他的一些格式,因为json中没有时间,ip等格式,统一为字符串,可以使用format关键字再进行定义。

定义字符串长度范围,值必须是非负数
{
  "type": "string",
  "minLength": 2,
  "maxLength": 3
}
  • 支持的参数
长度:minLength,maxLength
正则表达式 :pattern 
其他内置格式:对应使用format关键字:   "format":"",
	日期和时间:date-time;time;date;
	邮件地址:email;idn-email
	主机名:hostname
	IP:ipv4;ipv6
	资源标识符:uuid;uri 
	url模板:uri-template
	json指针:JSON Pointer
	正则表达式:regex
1:正则表达式

string支持正则表达式介绍。正则表达式规则介绍

.:匹配除换行符以外的任何字符。
^:仅在字符串的开头匹配。
$:仅在字符串末尾匹配。
(...):将一系列正则表达式组合成一个正则表达式。
|:匹配前面或后面的正则表达式|符号。
[abc]:匹配方括号内的任何字符。
[a-z]:匹配字符范围内的所有。
[^abc]:匹配字符以外的。
[^a-z]:匹配范围之外的任何字符。
+:匹配前面正则表达式的一个或多个重复。
*:匹配前面正则表达式的零个或多个重复。
?:匹配前面正则表达式的零个或一个重复。
+?,*?,??:该*,+,和?限定词都是贪婪的;它们匹配尽可能多的文本。有时这种行为是不可取的,您希望匹配尽可能少的字符。
(?!十),(?=x):消极和积极的前瞻。
{x}:完全匹配前面x位数正则表达式的出现。
{x,y}:至少匹配x最多y出现在前面位数的正则表达式。
{x,}:匹配x前面正则表达式的一次或多次出现。
{x}?,{x,y}?,{x,}?:上述表达式的懒惰版本。

demo:

{
   "type": "string",
   "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$",
}
//"(888)555-1212"   或者"555-1212"   都是符合的
// ^(([0-9]{3}))?  匹配0-9的数字匹配前3位,执行一次匹配或者0次
// [0-9]{3}			再匹配0-9的数子匹配3位,
// -[0-9]{4}$		-在数据末尾执行匹配0-9的数据匹配4位

2.2:数字类型

JSON模式中有两种数字类型:integer和number。它们共享相同的验证关键字。

  • integer:同于整数,不适用于小数点。
  • number:用于任何数值类型,整数或浮点数字。
    两者均可用于包括大写的一到十。

支持参数

倍数:multipleOf
范围:
	x ≥ minimum 
	x > exclusiveMinimum 
	x ≤ maximum
	x < exclusiveMaximum

2.3:object对象

对象是JSON中的映射类型。它们将“键”映射到“值”。在JSON中,“键”必须总是字符串。每一对通常被称为“property”。
{ “type”: “object” } :一个键值对也可以成为一个对象

object支持可选参数

{
  "type": "object",
  "properties": {},
  "patternProperties":{},
  "additionalProperties ":fasle或者true或者额外字段类型的定义,
 "required":[],
  "minProperties": 1,
  "maxProperties": 5
}
  • 1:properties
    properties 用于描述一个object对象的多个属性
{
  "type": "object",
  "properties": {
    "number": { "type": "number" }
  }
}

{ “number”: 1600}

  • 2:patternProperties
    对符合正则匹配的字段套用该定义
{
  "type": "object",
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  }
}

{ “S_25”: “This is a string” }

  • 3:additionalProperties 额外属性定义
{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
  "additionalProperties": { "type": "string" }   //允许存在未被定义的字段,类型必须是字符串
  }
}

“additionalProperties”: false//不允许存在未被定义的字段
{ “number”: 1600, “street_name”: “Pennsylvania”} //属性未被定义

  • 4:required必需
    必需存在的属性
 {
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "email": { "type": "string" },
    "address": { "type": "string" },
    "telephone": { "type": "string" }
  },
  "required": ["name", "email"]
}

demo

{
  "name": "William Shakespeare",
  "email": "bill@stratford-upon-avon.co.uk"
}
  • 4 propertyNames 对属性名称规则正则匹配
  • 5 size
    定义每个对象中属性个数
"minProperties": 1,
"maxProperties": 5

2.4:数组

数组包括list和元组tuple 。可以定义枚举值,唯一值,最大值,最小值,元素个数等参数。

  • 1:array
    数组中可以使用items关键字定义每个值的类型
{
  "type": "array",
  "items": {   //定义每个元素类型
    "type": "number"
  },
   "uniqueItems": true   //是否允许值重复
   "minItems": 2,   	 //最小元素个数
   "maxItems": 3  		//最大元素个数
}
  • 2:tuple元组
 "prefixItems": 
 "items":
 "contains":{},
 "minContains": 2,
 "maxContains": 3
 "minItems": 2,
 "maxItems": 3

2.5:boolean

{ “type”: “boolean” } 允许的值为true或者false

2.6:架构组合

使用下面关键字进行组合不同定义的匹配,使得对于属性定义必须满足几个或者全部的要求,允许同时根据多个标准验证一个值一样简单。类似于AND、OR。

allOf  必须对所有子模式有效
anyOf 必须对任何子模式有效
oneOf 必须符合其中一个字schema
not 都不符合

所有这些关键字都必须设置为一个数组,其中每个项目都是一个模式

1:allOf 必须都符合

demo:类型必须是string并且要求最大长度

{
  "allOf": [
    { "type": "string" },
    { "maxLength": 5 }
  ]
}
2:anyOf 任何一个符合
3:oneOf 其中一个符合
4:not 都不符合

可以通过additionalProperties=false或者true进行不同模式间的共享或者关闭

2.7:处理xml或txt等json数据

可以对于是xml或者text等不符合json的数据定义默认的类型,比如

{  //定义该字符串中是一个txt或者xml
  "type": "string",
  "contentMediaType": "text/html"
}

2.8:条件属性绑定

对于某些字段间约束为一定的依赖关系,比如name属性必须依赖于age属性存在,其中一个不存在都不行。可以使用关键字

dependentRequired  
	同时存在或者同时不存在,可以定义双向依赖或者单向依赖
if/then/else
  • dependentRequired 定义了两个字段单向依赖
"dependentRequired": {
    "credit_card": ["billing_address"]
  }
  • if/then/else 对于子模式间的互相依赖判断,调用逻辑验证
    如果country值是“”然后。。。。。。
{
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "default": "United States of America",
      "enum": ["United States of America", "Canada"]
    }
  }, 
  ### 上面是定义,下面可以进行判断条用不同的校验
  "if": {
    "properties": { "country": { "const": "United States of America" } }
  },
  "then": {
    "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
  },
  "else": {
    "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
  }
}

2.9:结构复杂组合示例

allof+ 依赖组成的复杂schema定义
如果满足country字段定义然后执行,否则执行,相当于is-else操作。

{
 "allOf": [
    {
      "if": {
        "properties": { "country": { "const": "United States of America" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
      }
    },
    {
      "if": {
        "properties": { "country": { "const": "Canada" } },
        "required": ["country"]
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
      }
    },
    {
      "if": {
        "properties": { "country": { "const": "Netherlands" } },
        "required": ["country"]
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } }
      }
    }
  ]
}

2.10:type支持的通用参数

标题或者注释:title and description
字段默认值:"default": 
枚举值:enum :[]     //属性含有多个值
固定值:const:某属性的值为固定的一个值,值相等才校验通过
  比如: "id": {
              "type": "string",
              "const": "id"
            },

3:构造一个复杂的schema( r e f 和 ref和 refdef)

可以定义不同的schema,在定义相同的部分直接进行互相引用,但是在schema中没有类似URL的定位符,但是有$ref和$def关键字进行资源位置标识。简单来说就是复用,和代码复用一样。

1:$ref关键字

使用$ref关键字引用#/definitions/Ref字段的定义。#代表这个schema,/代表跟路径。

{
  "properties": {
    "prop": {
      "$ref" : "#/definitions/Ref"
    }
  },
  "definitions" : {
    "Ref" : {
      "type" : "number"
    }
  }
}

4:JSON Schema开发实战

JSON Schema java实战
Java-JSON-工具/JSON-模式验证器
开发校验器推荐:
使用Jackson来处理Java代码中的JSON,使用:Java-JSON-工具/JSON-模式验证器
使用org.json API那么使用:JSON Schema everit-java实战

  • 推荐在线json和json-schema校验工具:https://www.jsonschemavalidator.net/
  • 推荐json转换为json-schema工具:https://tooltt.com/json2schema/

4.1:everit-org验证器

如果使用org.json解析处理json数据,则适合用everit-org检验器API。

  • 1:检验器:SchemaLoader类
    使用该类作为总入口,获取验证器
  • 2:对于验证的冲突如何解决,或者说如何处理异常:提供了ValidationException.getCausingExceptions()获取每一个校验失败原因。
    获取每一个异常并打印
try {
  schema.validate(rectangleMultipleFailures);  //检验
} catch (ValidationException e) { 		 //获取异常
  System.out.println(e.getMessage());    //输出异常
  e.getCausingExceptions().stream()  	 //打印每个异常
      .map(ValidationException::getMessage)
      .forEach(System.out::println);
}
  • 3:json格式验证:为了清楚具体的json是否符合某种支持的类型,可以使用默认的校验器(ipv4等),也可以实现ValidationListener 接口验证数据。
    Validator validator = Validator.builder() .withListener(new YourValidationListenerImplementation()) .build(); validator.performValidation(schema, input);
  • 4:监听的严格程度:对于验证的失败数据是否继续验证可以进行设置
1:maven开发依赖
<dependency>
    <groupId>com.github.everit-org.json-schema</groupId>
    <artifactId>org.everit.json.schema</artifactId>
    <version>1.14.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20201115</version>
 </dependency>

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

若上面依赖导入失败可用下方依赖,两者选用一个即可

<dependency>
            <groupId>com.networknt</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>1.0.63</version>
        </dependency>
        <dependency>
            <groupId>org.everit.json</groupId>
            <artifactId>org.everit.json.schema</artifactId>
            <version>1.5.1</version>
        </dependency
2:demo

json数据

{
  "name":"xiaoming",
  "age":99,
  "like":"baskball",
    "addr":{
      "city":"西安",
      "county":"chain"
    } 
}

schema规则

{
  "type": "object",
  "required": [],
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "number"
    },
    "like": {
      "type": "string"
    },
    "addr": {
      "type": "object",
      "required": [],
      "properties": {
        "city": {
          "type": "string"
        },
        "county": {
          "type": "string"
        }
      }
    }
  }
}

代码测试

 public static void main(String[] args) {
        /*加载schema文件*/
        InputStream jsonSchemaTest = jsonSchema.class.getClassLoader().getResourceAsStream("jsonSchemaTest.json");
        JSONObject jsonObject = new JSONObject(new JSONTokener(jsonSchemaTest));
        //将JSON schema的JSON加载到模式验证器实例中。
        Schema load = SchemaLoader.load(jsonObject);
        /*加载json文件*/
        InputStream jsonStream = jsonSchema.class.getClassLoader().getResourceAsStream("jsonSchema1Data.json");
//验证
        try {
            load.validate(new JSONObject(new JSONTokener(jsonStream)));
        } catch (ValidationException e) {
             e.getCausingExceptions();
            System.out.println("校验成功");
        }
    }

4.2:json-schema-validator校验器

1:maven依赖
<dependency>
    <groupId>com.github.java-json-tools</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>2.2.14</version>
</dependency>
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值