Java 中的 JSON Schema 和验证库

huangapple go评论77阅读模式
英文:

Library for Json Schema and Validation in Java

问题

我可以看到有一些可以生成 JSON Schema 并进行验证的库。您能否推荐一些在 Java 中同时提供这两种功能的库(附带示例和当前活跃的库)?我希望使用 Apache 许可的库。

我已经尝试过 Jackson 和 Gson。
Gson 不支持 JSON Schema 的创建和验证。
Jackson 支持生成 JSON Schema,但不是完全支持(例如,在 JSON Schema 中不支持默认值)。

谢谢,

英文:

I can see there are some libraries that generate Json Schema and other which can validate. Could you please suggest some library (with examples and active one) that can provide both functionality in Java. I am looking for Apache licensed library.

I have tried Jackson and Gson.
Gson does not support neither json schema creation and validation.
Jackson support json schema generation but not fully (e.g. it does not support default value in json schema)

Regards,

答案1

得分: 2

GSON和Jackson的主要范围是处理数据到JSON的序列化/反序列化,JSON模式的生成和验证并不是它们的(主要)关注点。

根据您在其他问题中的评论(如何在Jackson中显示JSON Schema的默认值),有一些关于模式生成的替代方案 - 同样适用于验证。

实现列表(生成和验证)

根据R.Groote的答案,您可以在https://json-schema.org/implementations.html找到其中一些(但不是全部) - 既有生成库也有验证库。

验证

就个人而言,我迄今只使用过networknt/json-schema-validator,发现它非常直观且易于使用。它在内部使用了Jackson,这在我的用例中很实用,因为我已经在将数据从/到JSON进行(反)序列化时使用了相同的库 - 因此减少了额外的依赖。


生成

> 免责声明:接下来是主观的部分,因为我是
> victools/jsonschema-generator的创建者。

JSON Schema生成库的一个示例是victools/jsonschema-generator。它也在内部使用Jackson,因此与networknt/json-schema-validator类似的依赖关系。

jsonschema-generator库不会默认填充“default”值,但您可以轻松地像这样配置它(基于Jackson的@JsonProperty注解,就像您的其他问题中一样):

SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2019_09, OptionPreset.PLAIN_JSON);
configBuilder.forFields().withDefaultResolver(field -> {
    JsonProperty annotation = field.getAnnotationConsideringFieldAndGetter(JsonProperty.class);
    return annotation == null || annotation.defaultValue().isEmpty() ? null : annotation.defaultValue());
});
SchemaGenerator generator = new SchemaGenerator(configBuilder.build());
JsonNode jsonSchema = generator.generateSchema(YourClass.class);

System.out.println(jsonSchema.toString());

如果您要处理数值类型的默认值,可能需要对@JsonProperty.defaultValueString进行一些条件解析。

另外,如果您希望对Jackson注解进行更具体的处理,还可以考虑添加可选的victools/jsonschema-module-jackson


编辑(回应您对在代码和注解中都需要定义默认值的担忧):

使用victools/jsonschema-generator,您可以完全控制默认值的来源。一个可能的方法是从遇到的实际对象实例中查找默认值 - 在这里可以通过过滤自己的包来跳过外部类型。
以下只是一个可能的示例:

ConcurrentMap<Class<?>, Object> instanceCache = new ConcurrentHashMap<>();
configBuilder.forFields().withDefaultResolver(field -&gt; {
    Class<?> declaringClass = field.getDeclaringType().getErasedType();
    if (!field.isFakeContainerItemScope()
            && declaringClass.getName().startsWith("your.package")) {
        MethodScope getter = field.findGetter();
        if (getter != null) {
            try {
                Object instance = instanceCache.computeIfAbsent(declaringClass, declaringClass::newInstance);
                Object defaultValue = getter.getRawMember().invoke(instance);
                return defaultValue;
            } catch (Exception ex) {
                // most likely missing a no-args constructor
            }
        }
    }
    return null;
});
英文:

The main scope of GSON and Jackson is to handle the serialization/deserialization of your data to/from JSON.
Both the generation and validation of JSON Schemas are not their (main) concern.

As per comments on your other question (How to display default value in JSON Schema using Jackson), there are a couple of alternatives out there for the schema generation – the same applies to their validation.

List of Implementations (Generation & Validation)

As per R.Groote's answer, you can find some (but not all) of them on https://json-schema.org/implementations.html – both generation and validation libraries.

Validation

Personally, I've only used networknt/json-schema-validator so far and found it very intuitive and easy to use. It uses Jackson under the hood, which was practical in my use-case as I was already using the same library for the (de)serialization of data from/to JSON – so less additional dependencies.


Generation

> Disclaimer: here comes the biased part as I'm the creator of
> victools/jsonschema-generator.

One example for a JSON Schema generation library would be victools/jsonschema-generator. That also uses Jackson internally, so again similar dependencies to the networknt/json-schema-validator.

The jsonschema-generator library does not populate the "default" value out-of-the-box, but you could easily configure it like this (based on the Jackson @JsonProperty annotation as per your other question):

SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2019_09, OptionPreset.PLAIN_JSON);
configBuilder.forFields().withDefaultResolver(field -&gt; {
    JsonProperty annotation = field.getAnnotationConsideringFieldAndGetter(JsonProperty.class);
    return annotation == null || annotation.defaultValue().isEmpty() ? null : annotation.defaultValue());
});
SchemaGenerator generator = new SchemaGenerator(configBuilder.build());
JsonNode jsonSchema = generator.generateSchema(YourClass.class);

System.out.println(jsonSchema.toString());

If you are catering for numeric default values, you might have to include some conditional parsing of the @JsonProperty.defaultValue String then.

Additionally, if you want some more specific handling of Jackson annotations you could also consider adding the optional victools/jsonschema-module-jackson as well then.


EDIT (as response to your concerns having to define the default values twice – in the code and on the annotation):

With the victools/jsonschema-generator you have full control over where the default value is coming from. One possible approach could be to look-up the default values from actual instances of the respective objects being encountered – here filtering by your own package to skip external types.
The following is just a rough example of what is possible:

ConcurrentMap&lt;Class&lt;?&gt;, Object&gt; instanceCache = new ConcurrentHashMap&lt;&gt;();
configBuilder.forFields().withDefaultResolver(field -&gt; {
    Class&lt;?&gt; declaringClass = field.getDeclaringType().getErasedType();
    if (!field.isFakeContainerItemScope()
            &amp;&amp; declaringClass.getName().startsWith(&quot;your.package&quot;)) {
        MethodScope getter = field.findGetter();
        if (getter != null) {
            try {
                Object instance = instanceCache.computeIfAbsent(declaringClass, declaringClass::newInstance);
                Object defaultValue = getter.getRawMember().invoke(instance);
                return defaultValue;
            } catch (Exception ex) {
                // most likely missing a no-args constructor
            }
        }
    }
    return null;
});

答案2

得分: 1

我更喜欢使用GSON或Jackson:

你可以使用Justify或json-schema-validator,查看下面的链接:

希望上面的链接能够为您提供足够的信息。

英文:

I prefer to use GSON or Jackson:

You could use Justify or json-schema-validator see below links:

I hope the above links give you enough information

huangapple
  • 本文由 发表于 2020年4月10日 16:13:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/61136401.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定