JSON解析器之jsonschema校验及代码实现
项⽬有个业务需要对JSON格式的数据校验,需要⼀些必要字段的验证,实现⼀个JSON解析器。所以学习了json schema的语法和解析器的实现。
本篇是先说通⽤的JSON验证,也就是json schema和在java代码中的校验使⽤。
json schema是什么
json schema实际上就是⼀个JSON⽂件,⽂件内容是对JSON数据的结构及内容的约束,就像是xml⽂件的xsd⽂件对xml的验证。
先看⼀下简单的schema内容
1 {
2  "$schema": "/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⽂件的描述信息,⾮必填
json值的类型有哪些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,boolean
string
maxLength: 校验string字符串的最⼤长度。超出长度校验失败。
minLength: 校验string字符串的最⼩长度。⼩于长度校验失败。
pattern: 字符串满⾜指定的正则表达式,才算通过校验。
format: 不常⽤,值只能是以下的取值date-time(时间格式)、email(邮件格式)、hostname(⽹站地址格式)、ipv4、ipv6、uri、uri-reference、uri-template、json-pointer。假如要校验的字符串是邮箱格式的可以使⽤"forma"t:"email",⽽不⽤pattern⾃⼰去指定正则表达式。
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数组中的所有元素都具有唯⼀性时,才能通过校验。
这⾥只是简单的列举了⼀些常⽤的关键字,如果想要学习更多的使⽤⽅法,可以去看下官⽅⽂档⾥⾯会有更详细的⽤例。
再分享两个链接
在程序中实现对json数据的校验
中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.</groupId>
10    <artifactId>jackson-core</artifactId>
11    <version>2.3.0</version>
12 </dependency>
13 <dependency>
14    <groupId>com.</groupId>
15    <artifactId>jackson-databind</artifactId>
16    <version>2.3.0</version>
17 </dependency>
将JSON数据转成jsonNode:
1/**
2    * @param jsonStr 验证json字符串
3*/
4private static JsonNode strToJsonNode(String jsonStr) {
5        JsonNode jsonNode = null;
6try {
7            jsonNode = JsonLoader.fromString(jsonStr);
8        } catch (IOException e) {
9            e.printStackTrace();
10        }
11return jsonNode;
12    }
获取本地的josn schema⽂件:
基于springboot项⽬,schema.json约束⽂件放在了resources/static/ ⽂件夹下
String jsonFilePath = "classpath:static/schema.json";
通过spring的⼯具类File(jsonFilePath)获取到⽂件的绝对路径
使⽤classpath:⽅法的好处就是不⽤在代码中写绝对路径。部署项⽬时不需要关⼼⽂件的位置。只要项⽬中的static⽂件中有schema.json⽂件就能获取到
1/**
2    * @param jsonFilePath jsonSchema⽂件路径
3*/
4private static JsonNode schemaToJsonNode(String jsonFilePath) {
5        JsonNode jsonSchemaNode=null;
6try {
7            jsonSchemaNode= new JsonNodeReader().fromReader(new File(jsonFilePath)));
8        } catch (IOException e) {
9            e.printStackTrace();
10        }
11return jsonSchemaNode;
12    }
schema校验代码实例:
1/**
2    * @param jsonNode  json数据node
3    * @param schemaNode jsonSchema约束node
4*/
5private static boolean getProcessingReport(JsonNode jsonNode, JsonNode schemaNode) {
6//fge验证json数据是否符合json schema约束规则
7        ProcessingReport report = JsonSchemaFactory.byDefault().getValidator().validateUnchecked(schemaNode, jsonNode);
8if (report.isSuccess()) {
9// 校验成功
10return true;
11        } else {
12            Iterator<ProcessingMessage> it = report.iterator();
13                StringBuilder ms = new StringBuilder();
14                ms.append("json格式错误: ");
15while (it.hasNext()) {
16                    ProcessingMessage pm = it.next();
17if (!LogLevel.WARNING.LogLevel())) {
18                        ms.append(pm);
19                    }
20                }
21                println(ms);
22return false;
23        }
24    }
写在最后
本篇⽂章只为了记录和分享⾃⼰学习的成果,能够帮助更多的⼩伙伴当然是更好了,如果有错误欢迎指出。谢谢!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。