这篇“java怎么校验json的格式是否符合要求”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“java怎么校验json的格式是否符合要求”文章吧。
JSON Schema
JSON Schema 是用于验证 JSON 数据结构的强大工具,Schema可以理解为模式或者规则。
Json Schema定义了一套词汇和规则,这套词汇和规则用来定义Json元数据,且元数据也是通过Json数据形式表达的。Json元数据定义了Json数据需要满足的规范,规范包括成员、结构、类型、约束等。
JSON Schema 就是json的格式描述、定义、模板,有了他就可以生成任何符合要求的json数据
json-schema-validator
在java中,对json数据格式的校验,使用
json-schema-validator
,具体实例如下:1. 引入依赖
<dependency>
<groupId>com.github.fge</groupId>
<artifactId>json-schema-validator</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
jackson-core
和 jackson-core
是必须要引入的,他们为 json-schema-validator
必须的2. 编写schema
如果我们要校验的数据格式如下:
{
"data": [
{
"sex": "男",
"name": "王小明",
"age": 18
},
{
"sex": "女",
"name": "王小红",
"age": 17
}
],
"type": "human"
}
外面是type和data,里面是一个数组,数组属性包括sex、name、age
编写schema文件
{
"type": "object",
"properties": {
"type": {
"type": "string"
},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 3
},
"sex": {
"enum": [
"男",
"女"
]
},
"age": {
"type": "number"
}
},
"required": [
"name",
"sex",
"age"
]
}
}
},
"required": [
"type",
"data"
]
}
以上json描述了目标json的数据格式,外层必须字段type、data,里面限制了name的最大长度
maxLength
为3,sex 为枚举值,只可取 男、女两个字符串,age 为number类型。3. 代码实现
public Map validatorJsonUnchecked(String body) {
Map<String, String> map = new HashMap<>();
String filePath = "validator" + File.separator + "validator.json";
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode jsonNodeSchema = objectMapper.readTree(ResourceUtil.readUtf8Str(filePath));
JsonNode jsonNode = objectMapper.readTree(body);
ProcessingReport processingReport = JsonSchemaFactory.byDefault().getValidator().validate(jsonNodeSchema, jsonNode, true);
if (!processingReport.isSuccess()) {
processingReport.forEach(processingMessage -> {
JsonNode missing = processingMessage.asJson().get("missing");
String keyword = processingMessage.asJson().get("keyword").asText();
// 如果缺失字段
if (!Objects.isNull(missing)) {
missing.forEach(miss -> {
String text = miss.asText();
map.put(text, text + " 字段缺失");
});
// 如果字段超长
} else if ("maxLength".equals(keyword)) {
String field = processingMessage.asJson().get("instance").get("pointer").asText();
String value = processingMessage.asJson().get("value").asText();
field = field.substring(field.lastIndexOf("/") + 1);
map.put(field, value + " 字段长度过长");
// 如果不在枚举范围内
} else if ("enum".equals(keyword)) {
String field = processingMessage.asJson().get("instance").get("pointer").asText();
String value = processingMessage.asJson().get("value").asText();
field = field.substring(field.lastIndexOf("/") + 1);
map.put(field, field + "字段值错误," + value + "不在枚举范围内");
} else if ("type".equals(keyword)) {
String field = processingMessage.asJson().get("instance").get("pointer").asText();
String found = processingMessage.asJson().get("found").asText();
String expected = processingMessage.asJson().get("expected").toString();
field = field.substring(field.lastIndexOf("/") + 1);
map.put(field, field + " 类型错误,现有类型: " + found + ", 预期类型:" + expected);
}
});
}
} catch (IOException | ProcessingException e) {
log.error("校验json格式异常", e);
}
return map;
}
以上代码首先获取了 要校验的json的标准文件
validator.json
,然后调用 JsonSchemaFactory.byDefault().getValidator().validate(jsonNodeSchema, jsonNode, true)
方法对传进来的json 进行了校验,这里 true
的意思是深度检查,如果没有这个参数,校验json的时候遇到第一个错误,就直接返回了接下来构建测试方法
public static void main(String[] args) {
ValidatorService validatorService = new ValidatorServiceImpl();
Map<String, Object> body = new HashMap<>();
HashMap<String, Object> one = new HashMap<String, Object>() {{
put("name", "王小明");
put("sex", "男");
put("age", 18);
}};
HashMap<String, Object> two = new HashMap<String, Object>() {{
put("name", "王小明1");
put("sex", "未知");
put("age", "18");
}};
body.put("type", "human");
body.put("data", Arrays.asList(one,two));
Map map = validatorService.validatorJsonUnchecked(JSONUtil.toJsonStr(body));
System.out.println(map);
}
4. 执行结果
{sex=sex字段值错误,未知不在枚举范围内, name=王小明1 字段长度过长, age=age 类型错误,现有类型: string, 预期类型:["integer","number"]}
5. 整理总结
如果schema 编写的时候,对列表使用了中括号
[]
,那么当校验的时候只会校验数组中的第一个,这是一个坑,如下{
"type": "object",
"properties": {
"type": {
"type": "string"
},
"data": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 3
},
"sex": {
"enum": [
"男",
"女"
]
},
"age": {
"type": "number"
}
},
"required": [
"name",
"sex",
"age"
]
}
]
}
},
"required": [
"type",
"data"
]
}
如果是这样的话,只会校验 data 数组的第一条数据,其他的有错误也不会报错!!