Сделайте подтипы Джексона расширяемыми без редактирования java-файла Supertypes - PullRequest
0 голосов
/ 29 апреля 2019

В моей компании есть фиксированная структура сообщений JSON:

{
    "headerVal1": ""
    "headerVal2": ""
    "customPayload": {
        "payloadType":""
    }
}

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

Моя идея состояла в том, чтобы определить структуру шаблона компании как один объект и использовать подтипы PayloadObject.

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.MINIMAL_CLASS,
    property = "payloadType",
    visible = false)
public abstract class PayloadObject {
}

Теперь я могу создавать подклассы PayloadObject, и его можно автоматически десериализовать в этой структуре, если свойство payloadType имеет строку ".SubTypeName".

Это проблематично, так как я не могу его настроить, даже удалить излишнее . в начале. К сожалению, это не обязательно совместимо с другими существующими в компании системами, с которыми нам нужно взаимодействовать.

Альтернативой является добавление @JsonSubTypes -аннотации, в которой я могу добавить все возможные подтипы - что я не хочу знать при написании библиотеки. Так что эта опция не будет работать для меня.

Я думал, это может помочь иметь @JsonType -аннотацию с подтипами, но мне все еще нужно добавить @JsonSubTypes, что не помогает.


Есть ли способ добавить подтипы к базовому типу без изменения java-файла базовых типов?


Если это поможет: мы работаем с Java Spring.

1 Ответ

0 голосов
/ 07 мая 2019

ObjectMapper имеет метод registerSubtypes(NamedType), который можно использовать для добавления подтипов для использования, не добавляя их в аннотации.

Для этого я создал новую аннотацию (возможно, я использовал @JsonTypeName, но это может быть оскорбительно)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyJsonSubtype
{
   public String jsonTypeName();
}

Тогда я написал мне метод

public static void registerMyJsonSubtypes(ObjectMapper om, Object... reflectionArgs) {
    Reflections reflections = new Reflections(reflectionArgs);
    Set<Class<?>> types = reflections.getTypesAnnotatedWith(MyJsonSubtype.class);
    for (Class type : types) {
        String name = ((MyJsonSubtype) type.getAnnotation(MyJsonSubtype.class)).jsonTypeName();
        om.registerSubtypes(new NamedType(type, name));
    }
}

, который использует Reflections для получения всех аннотированных типов, объявленных внутри найденных пакетов, и регистрирует их как подтипы для ObjectMapper.

Для этого по-прежнему требуется аннотация @JsonTypeInfo в базовом классе, чтобы пометить объект как потенциально расширяемый, поэтому маппер знает, какое свойство использовать для разрешения имени, но я полагаю, что это доказуемо. Мое основное внимание было уделено проблеме, заключающейся в том, что я не хочу объявлять все будущие подтипы в аннотации для базового класса.

Я новичок в Java, поэтому, пожалуйста, поделитесь своими мыслями, если это не нужно или может / должно / должно быть улучшено.

...