JSON解析器之json schema校验及代码实现

项目有个业务须要对JSON格式的数据校验,须要一些必要字段的验证,实现一个JSON解析器。因此学习了json schema的语法和解析器的实现。
本篇是先说通用的JSON验证,也就是json schema和在java代码中的校验使用。html

json schema是什么

json schema实际上就是一个JSON文件,文件内容是对JSON数据的结构及内容的约束,就像是xml文件的xsd文件对xml的验证。java

先看一下简单的schema内容node

 1 {  2   "$schema": "http://json-schema.org/draft-07/schema#",  3   "title": "这是个标题",  4   "description": "校验模板内容json格式",  5   "type": "object",  6   "properties": {  7     "name": { "type": "string" },  8     "credit_card": { "type": "number" },  9     "job_arr": { 10       "type": "array", 11       "items": { 12         "type": "string"
13  } 14  }, 15     "billing_address": { 16       "type": "object", 17       "properties": { 18         "selfId": { 19           "type": "string"
20  } 21  } 22  } 23  }, 24   "dependencies": { 25     "credit_card": ["billing_address"] 26  }, 27   "required": ["name"] 28 }

json schema关键字

关键字 描述
$schema 表示该JSON Schema使用的版本规范,非必填,目前最新一版“Draft-07”是2019.09发布的。每一个版本的语法可能有出入,方便之后人员维护建议使用
title JSON Schema文件的标题,非必填
description JSON Schema文件的描述信息,非必填
type 待校验元素的类型(例如,最外层的type表示待校验的是一个JSON对象,内层type分别表示待校验的元素类型为,number,string,array,object)
properties JSON对象中,各个key-value对中value的限制条件
required 校验的JSON对象中,必须存在的key,不存在则校验失败

typele类型常见的取值

string,object,array,integer(只能是int),number(float或者int),null,booleangit

  • string

maxLength: 校验string字符串的最大长度。超出长度校验失败。
minLength: 校验string字符串的最小长度。小于长度校验失败。
pattern: 字符串知足指定的正则表达式,才算经过校验。
format: 不经常使用,值只能是如下的取值date-time(时间格式)、email(邮件格式)、hostname(网站地址格式)、ipv四、ipv六、uri、uri-reference、uri-template、json-pointer。假如要校验的字符串是邮箱格式的可使用"forma"t:"email",而不用pattern本身去指定正则表达式。github

  • object

properties: 每一个key对应的值,都是一个json schema,则待校验JSON对象经过校验。从这里,咱们能够看到,json schema的校验检测,这个对象才算是经过校验。
required: 值是个字符串数组,数组元素是本级的属性key。该关键字限制了JSON对象中必须包含哪些本级key。若是固然json不包含数组中的key则校验失败。
dependencies: 设置属性依赖,值是一个json schema。例如
"dependencies": {"credit_card":["billing_address"]},
表示有字段"credit_card"就必须有"billing_address"字段。可是这个依赖是单向的。有"billing_address"字段能够没有"credit_card"。正则表达式

  • array

items: 值是一个有效的JSON Schema或者一组有效的JSON Schema。只有待校验JSON数组中的全部元素均经过校验,整个数组才算经过校验。
例如:{"type": "array","items": { "type": "string", "minLength": 5 }} 这个数组只有知足长度大于5才会经过校验
uniqueItems: 值是一个布尔值,即boolean(true、false)。当该关键字的值为true时,只有待校验JSON数组中的全部元素都具备惟一性时,才能经过校验。spring

这里只是简单的列举了一些经常使用的关键字,若是想要学习更多的使用方法,能够去看下官方文档里面会有更详细的用例。json

json schema中文使用教程文档数组

json schema draft-07版本官方文档springboot

json schema官网

再分享两个连接

根据json数据生成schema约束

使用schema约束验证json数据

在程序中实现对json数据的校验

json schema官网中java语言对json schema的实现方式有三种

  • everit-org/json-schema draft-07, -06, -04 (Apache License 2.0)
  • Justify draft-07, -06, -04 (Apache License 2.0)
  • networknt/json-schema-validator draft-07, -06, -04 Support OpenAPI 3.0 with Jackson parser (Apache License 2.0)

本篇介绍的是第三种---第三方工具feg

导入依赖fge包,由于fge的方法要用到jsonNode,因此也就须要导入jackson的包

 1 <!-- fge -->
 2 <dependency>  
 3     <groupId>com.github.fge</groupId>  
 4     <artifactId>json-schema-validator</artifactId>  
 5     <version>2.2.6</version>    
 6 </dependency>
 7 <!-- fasterxml -->
 8 <dependency>  
 9     <groupId>com.fasterxml.jackson.core</groupId>  
10     <artifactId>jackson-core</artifactId>  
11     <version>2.3.0</version>    
12 </dependency>  
13 <dependency>  
14     <groupId>com.fasterxml.jackson.core</groupId>  
15     <artifactId>jackson-databind</artifactId>  
16     <version>2.3.0</version>    
17 </dependency>

将JSON数据转成jsonNode:

 1     /**
 2  * @param jsonStr 验证json字符串  3      */
 4     private static JsonNode strToJsonNode(String jsonStr) {  5         JsonNode jsonNode = null;  6         try {  7             jsonNode = JsonLoader.fromString(jsonStr);  8         } catch (IOException e) {  9  e.printStackTrace(); 10  } 11         return jsonNode; 12     }

获取本地的josn schema文件:
基于springboot项目,schema.json约束文件放在了resources/static/ 文件夹下

String jsonFilePath = "classpath:static/schema.json";
经过spring的工具类ResourceUtils.getFile(jsonFilePath)获取到文件的绝对路径
使用classpath:方法的好处就是不用在代码中写绝对路径。部署项目时不须要关心文件的位置。只要项目中的static文件中有schema.json文件就能获取到

 1     /**
 2  * @param jsonFilePath jsonSchema文件路径  3      */
 4     private static JsonNode schemaToJsonNode(String jsonFilePath) {  5         JsonNode jsonSchemaNode=null;  6         try {  7             jsonSchemaNode= new JsonNodeReader().fromReader(new FileReader(ResourceUtils.getFile(jsonFilePath)));  8         } catch (IOException e) {  9  e.printStackTrace(); 10  } 11         return jsonSchemaNode; 12     }

schema校验代码实例:

 1     /**
 2  * @param jsonNode json数据node  3  * @param schemaNode jsonSchema约束node  4      */
 5    private static boolean getProcessingReport(JsonNode jsonNode, JsonNode schemaNode) {  6         //fge验证json数据是否符合json schema约束规则
 7         ProcessingReport report = JsonSchemaFactory.byDefault().getValidator().validateUnchecked(schemaNode, jsonNode);  8         if (report.isSuccess()) {  9             // 校验成功
10             return true; 11         } else { 12             Iterator<ProcessingMessage> it = report.iterator(); 13                 StringBuilder ms = new StringBuilder(); 14                 ms.append("json格式错误: "); 15                 while (it.hasNext()) { 16                     ProcessingMessage pm = it.next(); 17                     if (!LogLevel.WARNING.equals(pm.getLogLevel())) { 18  ms.append(pm); 19  } 20  } 21  System.err.println(ms); 22                 return false; 23  } 24     }

写在最后

本篇文章只为了记录和分享本身学习的成果,可以帮助更多的小伙伴固然是更好了,若是有错误欢迎指出。谢谢!

相关文章
相关标签/搜索