java校驗(yàn)json的格式是否符合要求的操作方法
在日常開發(fā)過程中,會(huì)有這樣的需求,校驗(yàn)?zāi)硞€(gè)json是否是我們想要的數(shù)據(jù)格式,如果每個(gè)層級去判斷,基本不太可能實(shí)現(xiàn),當(dāng)然java有開源的工具,我們可以直接使用
JSON Schema
JSON Schema 是用于驗(yàn)證 JSON 數(shù)據(jù)結(jié)構(gòu)的強(qiáng)大工具,Schema可以理解為模式或者規(guī)則。
Json Schema定義了一套詞匯和規(guī)則,這套詞匯和規(guī)則用來定義Json元數(shù)據(jù),且元數(shù)據(jù)也是通過Json數(shù)據(jù)形式表達(dá)的。Json元數(shù)據(jù)定義了Json數(shù)據(jù)需要滿足的規(guī)范,規(guī)范包括成員、結(jié)構(gòu)、類型、約束等。
JSON Schema 就是json的格式描述、定義、模板,有了他就可以生成任何符合要求的json數(shù)據(jù)
json-schema-validator
在java中,對json數(shù)據(jù)格式的校驗(yàn),使用 json-schema-validator,具體實(shí)例如下:
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 是必須要引入的,他們?yōu)?json-schema-validator 必須的
2. 編寫schema
如果我們要校驗(yàn)的數(shù)據(jù)格式如下:
{
"data": [
{
"sex": "男",
"name": "王小明",
"age": 18
},
{
"sex": "女",
"name": "王小紅",
"age": 17
}
],
"type": "human"
}外面是type和data,里面是一個(gè)數(shù)組,數(shù)組屬性包括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描述了目標(biāo)json的數(shù)據(jù)格式,外層必須字段type、data,里面限制了name的最大長度 maxLength 為3,sex 為枚舉值,只可取 男、女兩個(gè)字符串,age 為number類型。
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 + " 字段缺失");
});
// 如果字段超長
} 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 + " 字段長度過長");
// 如果不在枚舉范圍內(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 + " 類型錯(cuò)誤,現(xiàn)有類型: " + found + ", 預(yù)期類型:" + 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) 方法對傳進(jìn)來的json 進(jìn)行了校驗(yàn),這里 true 的意思是深度檢查,如果沒有這個(gè)參數(shù),校驗(yàn)json的時(shí)候遇到第一個(gè)錯(cuò)誤,就直接返回了
接下來構(gòu)建測試方法
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 字段長度過長, age=age 類型錯(cuò)誤,現(xiàn)有類型: string, 預(yù)期類型:["integer","number"]}
5. 整理總結(jié)
如果schema 編寫的時(shí)候,對列表使用了中括號 [],那么當(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ì)校驗(yàn) data 數(shù)組的第一條數(shù)據(jù),其他的有錯(cuò)誤也不會(huì)報(bào)錯(cuò)?。?/strong>
JSON Schema 功能很強(qiáng)大,支持表達(dá)式,支持是否允許額外屬性,支持邏輯組合等,如果想了解更新json校驗(yàn)的知識,請參考下面參考文檔
參考文檔
到此這篇關(guān)于java校驗(yàn)json的格式是否符合要求的文章就介紹到這了,更多相關(guān)java校驗(yàn)json格式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA?ServLet創(chuàng)建一個(gè)項(xiàng)目的基本步驟
Servlet是Server Applet的簡稱,是運(yùn)行在服務(wù)器上的小程序,用于編寫Java的服務(wù)器端程序,它的主要作用是接收并響應(yīng)來自Web客戶端的請求,下面這篇文章主要給大家介紹了關(guān)于JAVA?ServLet創(chuàng)建一個(gè)項(xiàng)目的基本步驟,需要的朋友可以參考下2024-03-03
詳解Spring系列之@ComponentScan批量注冊bean
本文介紹各種@ComponentScan批量掃描注冊bean的基本使用以及進(jìn)階用法和@Componet及其衍生注解使用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-02-02
SpringCloud開啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud開啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
Idea自定義方法注釋模板的教程詳解(去param括號、return全類名)
這篇文章主要介紹了Idea自定義方法注釋模板(去param括號、return全類名),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了使用Filter實(shí)現(xiàn)登錄權(quán)限驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Java編程實(shí)現(xiàn)統(tǒng)計(jì)一個(gè)字符串中各個(gè)字符出現(xiàn)次數(shù)的方法
這篇文章主要介紹了Java編程實(shí)現(xiàn)統(tǒng)計(jì)一個(gè)字符串中各個(gè)字符出現(xiàn)次數(shù)的方法,涉及java針對字符串的遍歷、判斷、運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
Spring Boot + Jpa(Hibernate) 架構(gòu)基本配置詳解
本篇文章主要介紹了Spring Boot + Jpa(Hibernate) 架構(gòu)基本配置詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Java位運(yùn)算和邏輯運(yùn)算的區(qū)別實(shí)例
Java位運(yùn)算和邏輯運(yùn)算的區(qū)別實(shí)例,請參考下面代碼,希望對你有所幫助2013-02-02
Java使用itext5實(shí)現(xiàn)PDF表格文檔導(dǎo)出
這篇文章主要介紹了Java使用itext5實(shí)現(xiàn)PDF表格文檔導(dǎo)出,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Springboot從配置文件properties讀取字符串亂碼的解決
這篇文章主要介紹了Springboot從配置文件properties讀取字符串亂碼的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02

