JSON Schema 校驗例項

weixin_33670713發表於2017-12-26

本文相關程式碼,請看這裡

JSON Schema 簡介

JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.

JSON Schema官網

JSON Schema 是一個可以對json格式資料進行校驗和進行內容描述的文件,它本身也是基於json格式的。
主要有以下作用:

  1. 對現有的json資料格式進行描述(欄位型別、內容長度、是否必須存在、取值示例等);
  2. 是一個描述清晰、人機可讀的文件;
  3. 自動測試、驗證客戶端提交的資料;

JSON Schema 簡單示例

我們把需要被驗證的json文件稱為instance,用來校驗它的文件就是schema;
一個最基礎的schema就是一個空的json物件 {} ,對instance不做任何限制,沒有任何描述。下面是一個簡單的instance和schema示例:

需要被校驗的instance:

{
  "foo": 32,
  "bar": "Must equal this value"
}

schema:

{
  "type": "object",
  "properties": {
    "foo": {
      "type": "number"
    },
    "bar": {
      "const": "Must equal this value"
    }
  }
}

其中關鍵字“type”可以用來對instance的型別進行限制,它可以取如下幾個值 object, array, string, number, boolean, null。
關鍵字“const”要求被驗證的資料與其所定義的內容保持一致。

JSON Schema 線上工具

根據JSON資料和對應的JSON Schema校驗資料:
http://json-schema-validator.herokuapp.com/
https://jsonschemalint.com/

根據JSON資料線上生成JSON Schema:
https://jsonschema.net/

JSON Schema第三方工具

JSON Schema已經有多種語言實現的第三方工具可以使用,詳見官網說明:http://json-schema.org/implementations。下面3個是java的相關實現:

json-schema-validator supports draft 4 includes draft-04 hype-schema syntax support (LGPLv3)
json-schema (implementation based on the org.json API) supports draft 4, draft 6 (Apache License 2.0)
json-schema-validator supports draft 4 (Apache License 2.0)

使用第三方工具json-schema-validator

下面使用上述3個工具中的第一個,實現用schema驗證json資料的功能:
1.首先在pom裡,新增如下配置:

                <!-- fge -->
        <dependency>
            <groupId>com.github.fge</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>2.2.6</version>
        </dependency>
        <!-- fasterxml -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.8</version>
        </dependency>

2.編寫工具類JsonSchemaValidator.java

public class JsonSchemaValidator {
    public static Map<String, Object> validateJsonByFgeByJsonNode(JsonNode jsonNode, JsonNode schemaNode) {
        Map<String, Object> result = new HashMap<String, Object>();
        ProcessingReport report = null;
        report = JsonSchemaFactory.byDefault().getValidator().validateUnchecked(schemaNode, jsonNode);
        if (report.isSuccess()) {
            // 校驗成功
            result.put("message", "校驗成功!");
            result.put("success", true);
            return result;
        } else {
            System.out.println("校驗失敗!");
            Iterator<ProcessingMessage> it = report.iterator();
            String ms = "";
            while (it.hasNext()) {
                ProcessingMessage pm = it.next();
                if (!LogLevel.WARNING.equals(pm.getLogLevel())) {
                    ms += pm;
                }

            }
            result.put("message", "校驗失敗!" + ms);
            result.put("success", false);
            return result;
        }
    }

    public static JsonNode getJsonNodeFromString(String jsonStr) {
        JsonNode jsonNode = null;
        try {
            jsonNode = JsonLoader.fromString(jsonStr);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonNode;
    }

    public static JsonNode getJsonNodeFromFile(String filePath) {
        JsonNode jsonNode = null;
        try {
            jsonNode = new JsonNodeReader().fromReader(new FileReader(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonNode;
    }

}

3.接收頁面資料、讀取檔案資料的JsonSchemaController

@RestController
public class JsonSchemaController {

    @Value("${upload.rootPath}")
    private String rootPath;


    @RequestMapping(value = "/json-schema/validate", method = RequestMethod.GET)
    public Map<String, Object> jsonSchemaValidate(String jsonStr) {
        Map<String, Object> result = new HashMap<String, Object>();

        JsonNode jsonNode = JsonSchemaValidator.getJsonNodeFromString(jsonStr);
        if (jsonNode == null) {
            result.put("success", false);
            result.put("message", "json報文格式錯誤");
            return result;
        }

        String filePath =  rootPath + "/json-file/json_schema_test.json";
        JsonNode schemaNode = JsonSchemaValidator.getJsonNodeFromFile(filePath);
        if (schemaNode == null) {
            result.put("success", false);
            result.put("message", "json Schema檔案不存在,無法校驗!");
            return result;
        }
        return JsonSchemaValidator.validateJsonByFgeByJsonNode(jsonNode, schemaNode);
    }

}

3.前端頁面json_schema.html

<body class=" ">
    <div>
        <textarea class=" " name="parameterContentLeft" id="parameterContentLeft" placeholder="請輸入請求報文內容"></textarea>
    </div>
    <br>
    <button onclick="setAjaxRequest();" id="doJson" class=" ">傳送</button>
    <div class=" ">
        <pre id="responsePre">

        </pre>
    </div>
    <script src="frame/jquery.min.js"></script>
    <script>
        function setAjaxRequest() {
            $.ajax({
                url : "/json-schema/validate",
                type : "GET",
                data : {
                    jsonStr : $("#parameterContentLeft").val()
                },
                async : false
            }).done(function(data) {
                $("#responsePre").html(data.message);
            });
        }
    </script>
</body>

測試功能

下面使用上面提到的線上生成scheme的工具裡提供的樣例,測試下我們剛才編寫的程式碼:
instance:

{
  "checked": false,
  "dimensions": {
    "width": 5,
    "height": 10
  },
  "id": 1,
  "name": "A green door",
  "price": 12.5,
  "tags": [
    "home",
    "green"
  ]

schema過長,就不貼了,詳見這裡

在頁面進行測試,效果如下:


5475410-d031fac9214499cf.png
image

把 "width": 5 改為 "width": 5.5,測試效果:


5475410-c60ef0d3d52daeb6.png
qq 20171226130003

在2個線上測試工具上測試效果:


5475410-1cba42be67e1261e.png
qq 20171226121604

5475410-0aacaba1649e6719.png
qq 20171226121733

可以看到2個線上測試工具,一個輸出了錯誤資訊和警告資訊,另一個只輸出了錯誤資訊。而我們本地開發的工具只輸出了錯誤資訊,是因為我把警告過濾掉了,這個可以根據實際需求進行修改。

相關文章