java校驗(yàn)json的格式是否符合要求的操作方法
在日常開(kāi)發(fā)過(guò)程中,會(huì)有這樣的需求,校驗(yàn)?zāi)硞€(gè)json是否是我們想要的數(shù)據(jù)格式,如果每個(gè)層級(jí)去判斷,基本不太可能實(shí)現(xiàn),當(dāng)然java有開(kāi)源的工具,我們可以直接使用
JSON Schema
JSON Schema 是用于驗(yàn)證 JSON 數(shù)據(jù)結(jié)構(gòu)的強(qiáng)大工具,Schema可以理解為模式或者規(guī)則。
Json Schema定義了一套詞匯和規(guī)則,這套詞匯和規(guī)則用來(lái)定義Json元數(shù)據(jù),且元數(shù)據(jù)也是通過(guò)Json數(shù)據(jù)形式表達(dá)的。Json元數(shù)據(jù)定義了Json數(shù)據(jù)需要滿(mǎn)足的規(guī)范,規(guī)范包括成員、結(jié)構(gòu)、類(lèi)型、約束等。
JSON Schema 就是json的格式描述、定義、模板,有了他就可以生成任何符合要求的json數(shù)據(jù)
json-schema-validator
在java中,對(duì)json數(shù)據(jù)格式的校驗(yàn),使用 json-schema-validator,具體實(shí)例如下:
1. 引入依賴(lài)
<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 是必須要引入的,他們?yōu)?json-schema-validator 必須的
2. 編寫(xiě)schema
如果我們要校驗(yàn)的數(shù)據(jù)格式如下:
{
"data": [
{
"sex": "男",
"name": "王小明",
"age": 18
},
{
"sex": "女",
"name": "王小紅",
"age": 17
}
],
"type": "human"
}外面是type和data,里面是一個(gè)數(shù)組,數(shù)組屬性包括sex、name、age
編寫(xiě)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描述了目標(biāo)json的數(shù)據(jù)格式,外層必須字段type、data,里面限制了name的最大長(zhǎng)度 maxLength 為3,sex 為枚舉值,只可取 男、女兩個(gè)字符串,age 為number類(lèi)型。
3. 代碼實(shí)現(xiàn)
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 + " 字段缺失");
});
// 如果字段超長(zhǎng)
} 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 + " 字段長(zhǎng)度過(guò)長(zhǎng)");
// 如果不在枚舉范圍內(nèi)
} 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 + "字段值錯(cuò)誤," + value + "不在枚舉范圍內(nèi)");
} 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 + " 類(lèi)型錯(cuò)誤,現(xiàn)有類(lèi)型: " + found + ", 預(yù)期類(lèi)型:" + expected);
}
});
}
} catch (IOException | ProcessingException e) {
log.error("校驗(yàn)json格式異常", e);
}
return map;
}以上代碼首先獲取了 要校驗(yàn)的json的標(biāo)準(zhǔn)文件 validator.json,然后調(diào)用 JsonSchemaFactory.byDefault().getValidator().validate(jsonNodeSchema, jsonNode, true) 方法對(duì)傳進(jìn)來(lái)的json 進(jìn)行了校驗(yàn),這里 true 的意思是深度檢查,如果沒(méi)有這個(gè)參數(shù),校驗(yàn)json的時(shí)候遇到第一個(gè)錯(cuò)誤,就直接返回了
接下來(lái)構(gòu)建測(cè)試方法
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. 執(zhí)行結(jié)果
{sex=sex字段值錯(cuò)誤,未知不在枚舉范圍內(nèi), name=王小明1 字段長(zhǎng)度過(guò)長(zhǎng), age=age 類(lèi)型錯(cuò)誤,現(xiàn)有類(lèi)型: string, 預(yù)期類(lèi)型:["integer","number"]}
5. 整理總結(jié)
如果schema 編寫(xiě)的時(shí)候,對(duì)列表使用了中括號(hào) [],那么當(dāng)校驗(yàn)的時(shí)候只會(huì)校驗(yàn)數(shù)組中的第一個(gè),這是一個(gè)坑,如下
{
"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"
]
}如果是這樣的話(huà),只會(huì)校驗(yàn) data 數(shù)組的第一條數(shù)據(jù),其他的有錯(cuò)誤也不會(huì)報(bào)錯(cuò)!!
JSON Schema 功能很強(qiáng)大,支持表達(dá)式,支持是否允許額外屬性,支持邏輯組合等,如果想了解更新json校驗(yàn)的知識(shí),請(qǐng)參考下面參考文檔
參考文檔
到此這篇關(guān)于java校驗(yàn)json的格式是否符合要求的文章就介紹到這了,更多相關(guān)java校驗(yàn)json格式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Java匯總Spock框架Mock靜態(tài)資源經(jīng)驗(yàn)
這篇文章主要介紹了基于Java匯總Spock框架Mock靜態(tài)資源經(jīng)驗(yàn),前面講了?Spock框架Mock對(duì)象、方法經(jīng)驗(yàn)總結(jié),今天分享一下Spock框架中Mock靜態(tài)資源的實(shí)踐經(jīng)驗(yàn)匯總。分成靜態(tài)資源和混合場(chǎng)景,需要的朋友可以參考一下2022-02-02
Java模擬rank/over函數(shù)實(shí)現(xiàn)獲取分組排名的方法詳解
這篇文章主要為大家詳細(xì)介紹了Java模擬rank()、over()函數(shù)獲取分組排名的方法設(shè)計(jì)及實(shí)現(xiàn),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04
webuploader在springMVC+jquery+Java開(kāi)發(fā)環(huán)境下的大文件分片上傳的實(shí)例代碼
這篇文章主要介紹了webuploader在springMVC+jquery+Java開(kāi)發(fā)環(huán)境下的大文件分片上傳的實(shí)例代碼,需要的朋友可以參考下2017-04-04
詳細(xì)介紹idea如何設(shè)置類(lèi)頭注釋和方法注釋(圖文)
本篇文章主要介紹了idea如何設(shè)置類(lèi)頭注釋和方法注釋(圖文),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
spring使用OXM進(jìn)行對(duì)象XML映射解析
這篇文章主要介紹了spring使用OXM進(jìn)行對(duì)象XML映射解析,具有一定借鑒價(jià)值,需要的朋友可以參考下2017-12-12

