当前位置: 首页 > 图灵资讯 > 技术篇> java校验json的格式是否符合要求

java校验json的格式是否符合要求

来源:图灵教育
时间:2023-05-31 09:21:49


java验证json格式是否符合要求

在日常开发过程中,会有这样的需求来验证json是否是我们想要的数据格式。如果判断每个层次,基本上不可能实现。当然,java有开源工具,我们可以直接使用它

JSON Schema

JSON Schema 是用于验证 JSON Schema可以理解为强大的数据结构工具的模式或规则。

Json Schema定义了一套定义Json元数据的词汇和规则,元数据也以Json数据的形式表达。Json元数据定义了Json数据需要满足的规范,包括成员、结构、类型、约束等。

JSON Schema 它是json的格式描述、定义和模板。有了他,任何符合要求的json数据都可以生成

json-schema-validator

在java中,使用json数据格式进行验证 json-schema-validator,具体例子如下:

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-corejackson-core 必须引入,他们是为了 json-schema-validator 必须的

2. 写schema

若要验证的数据格式如下:

{    "data": [        {            "sex": "男",            "name": “王小明”,            "age": 18        },        {            "sex": "女",            "name": “王小红”,            "age": 17        }    ],    "type": "human"}

外面是type和data,里面是一个数组,包括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描述了目标json的数据格式,外层必须字段type、data,内部限制了name的最大长度 maxLength 为3,sex 为枚举值,只能取 男女字符串,age 为number类型。

3. 代码实现

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 + " 字段长度过长”);                        // 若不在枚举范围内                    } 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 + “字段值错误," + value + "不在枚举范围内";                    } 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 + " 类型错误,现有类型: " + found + ", 预期类型:“ + expected);                    }                });            }        } catch (IOException | ProcessingException e) {            log.error(“Json格式异常验证”, e);        }        return map;    }

上述代码首先获得 json的标准文件需要验证 validator.json,然后调用 JsonSchemaFactory.byDefault().getValidator().validate(jsonNodeSchema, jsonNode, true) 方法对传进的json进行json 在这里进行校验 true 这意味着深度检查。如果没有这个参数,在检查json时遇到第一个错误,它将直接返回

接下来,构建测试方法

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. 执行结果

{sex=sex字段值错误,未知不在枚举范围内, name=王小明1 字段长度过长, age=age 类型错误,现有类型: string, 预期类型:["integer","number"]}

5. 整理总结

假如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"    ]}

如果是这样的话,只会验证 data 数组第一条数据,其他错误不会报错!!

JSON Schema 功能强大,支持表达式,支持是否允许额外属性,支持逻辑组合等。如果您想了解更新json校验的知识,请参考以下参考文件

参考文档

<https://www.tulingxueyuan.cn/d/file/p/20230531/hm3vozp3zuq.html