JSON解析器之json schema校驗及代碼實現

項目有個業務需要對JSON格式的數據校驗,需要一些必要字段的驗證,實現一個JSON解析器。所以學習了json schema的語法和解析器的實現。
本篇是先說通用的JSON驗證,也就是json schema和在java代碼中的校驗使用。

json schema是什麼

json schema實際上就是一個JSON文件,文件內容是對JSON數據的結構及內容的約束,就像是xml文件的xsd文件對xml的驗證。

先看一下簡單的schema內容

 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 }

json schema關鍵字

關鍵字 描述
$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,不存在則校驗失敗

typele類型常見的取值

string,object,array,integer(只能是int),number(float或者int),null,boolean

  • string

maxLength: 校驗string字符串的最大長度。超出長度校驗失敗。
minLength: 校驗string字符串的最小長度。小於長度校驗失敗。
pattern: 字符串滿足指定的正則表達式,纔算通過校驗。
format: 不常用,值只能是以下的取值date-time(時間格式)、email(郵件格式)、hostname(網站地址格式)、ipv4、ipv6、uri、uri-reference、uri-template、json-pointer。假如要校驗的字符串是郵箱格式的可以使用"forma"t:"email",而不用pattern自己去指定正則表達式。

  • object

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"。

  • array

items: 值是一個有效的JSON Schema或者一組有效的JSON Schema。只有待校驗JSON數組中的所有元素均通過校驗,整個數組纔算通過校驗。
例如:{"type": "array","items": { "type": "string", "minLength": 5 }} 這個數組只有滿足長度大於5纔會通過校驗
uniqueItems: 值是一個布爾值,即boolean(true、false)。當該關鍵字的值爲true時,只有待校驗JSON數組中的所有元素都具有唯一性時,才能通過校驗。

這裏只是簡單的列舉了一些常用的關鍵字,如果想要學習更多的使用方法,可以去看下官方文檔裏面會有更詳細的用例。

json schema中文使用教程文檔

json schema draft-07版本官方文檔

json schema官網

再分享兩個鏈接

根據json數據生成schema約束

使用schema約束驗證json數據

在程序中實現對json數據的校驗

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     }

寫在最後

本篇文章只爲了記錄和分享自己學習的成果,能夠幫助更多的小夥伴當然是更好了,如果有錯誤歡迎指出。謝謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章