Java 使用注释的多模式生成器

Java multi-schema generator using annotations

我有一系列相互关联的 Java classes,它们构成了可能模式的超集。我正在寻找一些方法来 annotate/tag 各个字段,以便我可以为每个 'namespace'.

创建单独的 JSON 模式

一个简单的例子:

class SupersetClass {
    @BelongsToSchema(schema={"alice"}, description="foo")
    Integer a;

    @BelongsToSchema(schema={"alice", "bob"}, description="bar")
    String b;

    @BelongsToSchema(schema={"bob"}, description="")
    Long c;
} 

输出会有单独的 Alice 和 Bob 模式,其中 Alice 有 a 和 b,Bob 有 b 和 c。

我目前的想法是遍历我想要生成的模式,然后使用反射创建一个自定义派生 class 并将其传递给 jackson-mapper,但是如果已经有一个这样做的好方法。

Disclaimer: I'm the maintainer of the victools/jsonschema-generator library mentioned below.

如果您不打算使用(稍微过时的)FasterXML/jackson-module-jsonSchema, you could use the victools/jsonschema-generator 库。后者支持更新的 JSON Schema Draft 版本,并在最终生成的模式中为您提供了很大的灵活性。但是,它(至少到今天为止)不支持开箱即用的相同范围的杰克逊特定注释。

也就是说,有多种方法可以解决您的问题。

1。简单地忽略属于不同上下文的属性

SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(
    SchemaVersion.DRAFT_2019_09, OptionPreset.PLAIN_JSON);
configBuilder.forFields()
    .withIgnoreCheck(field -> {
        BelongsToSchema annotation = field.getAnnotation(BelongsToSchema.class);
        return annotation != null
            && !Arrays.asList(annotation.schema()).contains("alice");
    });

2。在提及它们时排除来自不同上下文的属性模式

configBuilder.forFields()
    .withTargetTypeOverridesResolver(field -> {
        BelongsToSchema annotation = field.getAnnotation(BelongsToSchema.class);
        if (annotation == null || Arrays.asList(annotation.value()).contains("alice")) {
            return null;
        }
        return Collections.singletonList(field.getContext().resolve(Object.class));
    });

3。包括外部 $ref 而不是实际的子模式

configBuilder.forFields()
    .withCustomDefinitionProvider((field, context) -> {
        BelongsToSchema annotation = field.getAnnotation(BelongsToSchema.class);
        if (annotation == null || Arrays.asList(annotation.value()).contains("alice")) {
            return null;
        }
        ObjectNode customSubschema = context.getGeneratorConfig().createObjectNode()
                .put(SchemaKeyword.TAG_REF.forVersion(SchemaVersion.DRAFT_2019_09),
                        "https://your-external.ref/" + field.getSimpleTypeDescription());
        return new CustomPropertyDefinition(customSubschema);
    });

根据您的具体需求,可能还有更多可能性。

我鼓励您尝试一下,看看 documentation. If you have project-specific questions, feel free to raise those as Issues on GitHub