GSON 和 Jackson 的主要范围是处理数据与 JSON 之间的序列化/反序列化。
JSON Schema 的生成和验证都不是他们的(主要)关注点。
根据您的其他问题 (How to display default value in JSON Schema using Jackson) 中的 cmets,有几个替代方案可用于生成模式 - 这同样适用于它们的验证。
实现列表(生成和验证)
根据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 库不会填充开箱即用的“默认”值,但您可以像这样轻松配置它(根据您的其他问题,基于 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.defaultValue String 的一些条件解析。
此外,如果您想要对 Jackson 注释进行更具体的处理,您还可以考虑添加可选的 victools/jsonschema-module-jackson。
编辑(作为对您必须在代码和注释中定义两次默认值的担忧的回应):
使用victools/jsonschema-generator,您可以完全控制默认值的来源。一种可能的方法是从遇到的各个对象的实际实例中查找默认值——这里通过您自己的包过滤以跳过外部类型。
以下只是可能的粗略示例:
ConcurrentMap<Class<?>, Object> instanceCache = new ConcurrentHashMap<>();
configBuilder.forFields().withDefaultResolver(field -> {
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;
});