java校验json的格局是否符合要求
在日常开发过程中,会有这样的需求,校验某个json是否是咱们想要的数据格局,假如每个层级去判别,基本不太可能完成,当然java有开源的东西,咱们能够直接使用
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 数组的第一条数据,其他的有过错也不会报错!!
JSON Schema 功用很强大,支撑表达式,支撑是否允许额定属性,支撑逻辑组合等,假如想了解更新json校验的知识,请参阅下面参阅文档
参阅文档
www.cnblogs.com/terencezhou…
json-schema.apifox.cn/
www.nuomiphp.com/a/stackover…