验证 JSON 并提供自定义验证报告

wes*_*eyy 5 java validation json

我有一个接收 JSON 的应用程序,收到后应该验证它。验证由几个步骤组成。

  1. 如果接收到的对象是格式正确的 JSON
  2. 如果所有必填字段都存在
  3. 如果满足所有字段约束(即字符串大小)
  4. 如果满足条件依赖关系(如果某个字段的值为 A,则另一个字段的值为 B)

根据所描述的要求,如果违反任何约束,我应该生成自己的、专门格式化的验证报告对象

我考虑了几种方法来做到这一点,但我对任何一种都不满意,希望得到你们的建议,如何做到这一点。我考虑过的:

想法#1:Jackson + JSR303 bean 验证

@CustomConstraintIfAThenB // this should emulate the conditional dependency
public class Message {
    @JsonProperty(value = "a", required = true)
    @Size(min = 3, max = 8)
    private String a;

    @JsonProperty(value = "b", required = true)
    @Size(min = 5, max = 9)
    private String b;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

我发现这种方法的问题是在生成报告时,因为首先我需要使用 JacksonObjectMapper来尝试创建我的 POJO。如果这抛出,JsonProcessingException我应该解析它,并创建我的报告。如果没有抛出,只有这样我才能使用我的 bean 验证器进行验证(即。Hibernate)。

MyReport report = null;
Message m = null;

// first Jackson validation
try {
    m = objectMapper.treeToValue(json, Message.class);
} catch (JsonProcessingException e) {
    report = myExceptionParser.parse(e);
}

// second bean (field) validation
Set<ConstraintViolation<Message>> violations = validator.validate(m);
if (violations.size() > 0) {
    report = myViolationsParser.parse(violations);
}
Run Code Online (Sandbox Code Playgroud)

最大的问题是通过实际解析JsonProcessingException来创建我的自定义报告。并另外解析violations. 我应该编写两个解析器,其中之一(解析异常的那个)可能会非常笨拙。

想法#2:针对 JSON 模式进行验证

我可以编写一个 JSON 模式,然后根据该模式验证传入的 JSON。这样做的好处是,我将拥有一份由我正在使用的 JSON 模式验证器生成的独特、一致的报告,并且我应该只为其编写一个解析器。例如,如果我要使用fge-validator

JsonSchema schema = JsonSchemaFactory.byDefault().getJsonSchema(mySchema);
ProcessingReport report = mySchema.validate(json);

// only have one parser to parse the report to my custom report
MyReport = myReportParser.parse(report);
Run Code Online (Sandbox Code Playgroud)

问题在于,JSON Schema v4在处理条件依赖项时变得非常笨拙,因为没有 IF-THEN-ELSE 关键字。我找不到支持 JSON Schema v7 的库。此外,修改大型 JSON 架构可能会很棘手并且很容易出错。在这种情况下,类注释也会更好。

是否有第三种方法可以进行 JSON 验证并从中创建自定义报告,这种方法比较优雅,并且不像编写两个解析器(其中一个解析器解析异常)那样笨拙?

另请注意,我的 JSON 文件可以轻松拥有 200 多个字段,因此逐个字段编写自定义反序列化器可能不是一种选择。

我想就此获得一些建议,因为我确实找不到合理的方法来做到这一点。