Java Генератор нескольких схем с использованием аннотаций - PullRequest
0 голосов
/ 18 июня 2020

У меня есть серия взаимосвязанных Java классов, которые образуют суперпредставление возможных схем. Я ищу способ аннотировать / пометить отдельные поля, чтобы я мог создать отдельную схему JSON для каждого «пространства имен».

Простой пример:

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

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

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

Вывод будет иметь отдельные схемы Алисы и Боба, где Алиса имеет a и b, а Боб имеет b и c.

Моя текущая идея - перебрать схему, которую я хотел бы сгенерировать, а затем использовать отражение для создания настраиваемый производный класс и передайте его в jackson-mapper, но это вполне OTT, если уже есть хороший способ сделать это.

1 Ответ

1 голос
/ 19 июня 2020

Заявление об ограничении ответственности: я поддерживаю библиотеку victools/jsonschema-generator, упомянутую ниже.

Если вы не намерены использовать (немного устаревший) FasterXML / jackson-module-jsonSchema , вы можете использовать библиотеку victools / jsonschema-generator . Последний поддерживает более новые версии JSON Schema Draft и дает вам большую гибкость с точки зрения того, что попадает в созданную вами схему. Однако он (по крайней мере, на сегодняшний день) не поддерживает тот же диапазон специальных c аннотаций Джексона из коробки.

При этом есть несколько способов go о о чем вы спрашиваете.

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);
    });

Вероятно, есть еще несколько возможностей в зависимости от того, что именно вы хотите.

Я рекомендую вам поиграть с этим немного и взгляните на вики проекта . Если у вас есть вопросы по проекту c, не стесняйтесь поднимать их как Проблемы на GitHub .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...