項目有個業務須要對JSON格式的數據校驗,須要一些必要字段的驗證,實現一個JSON解析器。因此學習了json schema的語法和解析器的實現。
本篇是先說通用的JSON驗證,也就是json schema和在java代碼中的校驗使用。html
json schema實際上就是一個JSON文件,文件內容是對JSON數據的結構及內容的約束,就像是xml文件的xsd文件對xml的驗證。java
先看一下簡單的schema內容node
1 { 2 "$schema": "http://json-schema.org/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 }
關鍵字 | 描述 |
---|---|
$schema | 表示該JSON Schema使用的版本規範,非必填,目前最新一版「Draft-07」是2019.09發佈的。每一個版本的語法可能有出入,方便之後人員維護建議使用 |
title | JSON Schema文件的標題,非必填 |
description | JSON Schema文件的描述信息,非必填 |
type | 待校驗元素的類型(例如,最外層的type表示待校驗的是一個JSON對象,內層type分別表示待校驗的元素類型爲,number,string,array,object) |
properties | JSON對象中,各個key-value對中value的限制條件 |
required | 校驗的JSON對象中,必須存在的key,不存在則校驗失敗 |
string,object,array,integer(只能是int),number(float或者int),null,booleangit
maxLength: 校驗string字符串的最大長度。超出長度校驗失敗。
minLength: 校驗string字符串的最小長度。小於長度校驗失敗。
pattern: 字符串知足指定的正則表達式,纔算經過校驗。
format: 不經常使用,值只能是如下的取值date-time(時間格式)、email(郵件格式)、hostname(網站地址格式)、ipv四、ipv六、uri、uri-reference、uri-template、json-pointer。假如要校驗的字符串是郵箱格式的可使用"forma"t:"email",而不用pattern本身去指定正則表達式。github
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"。正則表達式
items: 值是一個有效的JSON Schema或者一組有效的JSON Schema。只有待校驗JSON數組中的全部元素均經過校驗,整個數組纔算經過校驗。
例如:{"type": "array","items": { "type": "string", "minLength": 5 }} 這個數組只有知足長度大於5纔會經過校驗
uniqueItems: 值是一個布爾值,即boolean(true、false)。當該關鍵字的值爲true時,只有待校驗JSON數組中的全部元素都具備惟一性時,才能經過校驗。spring
這裏只是簡單的列舉了一些經常使用的關鍵字,若是想要學習更多的使用方法,能夠去看下官方文檔裏面會有更詳細的用例。json
json schema draft-07版本官方文檔springboot
再分享兩個連接
json schema官網中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.fasterxml.jackson.core</groupId> 10 <artifactId>jackson-core</artifactId> 11 <version>2.3.0</version> 12 </dependency> 13 <dependency> 14 <groupId>com.fasterxml.jackson.core</groupId> 15 <artifactId>jackson-databind</artifactId> 16 <version>2.3.0</version> 17 </dependency>
將JSON數據轉成jsonNode:
1 /** 2 * @param jsonStr 驗證json字符串 3 */ 4 private static JsonNode strToJsonNode(String jsonStr) { 5 JsonNode jsonNode = null; 6 try { 7 jsonNode = JsonLoader.fromString(jsonStr); 8 } catch (IOException e) { 9 e.printStackTrace(); 10 } 11 return jsonNode; 12 }
獲取本地的josn schema文件:
基於springboot項目,schema.json約束文件放在了resources/static/ 文件夾下
String jsonFilePath = "classpath:static/schema.json";
經過spring的工具類ResourceUtils.getFile(jsonFilePath)獲取到文件的絕對路徑
使用classpath:方法的好處就是不用在代碼中寫絕對路徑。部署項目時不須要關心文件的位置。只要項目中的static文件中有schema.json文件就能獲取到
1 /** 2 * @param jsonFilePath jsonSchema文件路徑 3 */ 4 private static JsonNode schemaToJsonNode(String jsonFilePath) { 5 JsonNode jsonSchemaNode=null; 6 try { 7 jsonSchemaNode= new JsonNodeReader().fromReader(new FileReader(ResourceUtils.getFile(jsonFilePath))); 8 } catch (IOException e) { 9 e.printStackTrace(); 10 } 11 return jsonSchemaNode; 12 }
schema校驗代碼實例:
1 /** 2 * @param jsonNode json數據node 3 * @param schemaNode jsonSchema約束node 4 */ 5 private static boolean getProcessingReport(JsonNode jsonNode, JsonNode schemaNode) { 6 //fge驗證json數據是否符合json schema約束規則 7 ProcessingReport report = JsonSchemaFactory.byDefault().getValidator().validateUnchecked(schemaNode, jsonNode); 8 if (report.isSuccess()) { 9 // 校驗成功 10 return true; 11 } else { 12 Iterator<ProcessingMessage> it = report.iterator(); 13 StringBuilder ms = new StringBuilder(); 14 ms.append("json格式錯誤: "); 15 while (it.hasNext()) { 16 ProcessingMessage pm = it.next(); 17 if (!LogLevel.WARNING.equals(pm.getLogLevel())) { 18 ms.append(pm); 19 } 20 } 21 System.err.println(ms); 22 return false; 23 } 24 }
本篇文章只爲了記錄和分享本身學習的成果,可以幫助更多的小夥伴固然是更好了,若是有錯誤歡迎指出。謝謝!