У меня есть класс CloudEvent<T>
, который использует полиморфную десериализацию с использованием Джексона (2.9.0 - последняя версия), например:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CloudEvent<T> {
@NonNull
private String eventType;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "eventType",
defaultImpl = Void.class)
@JsonSubTypes({
@JsonSubTypes.Type(value = MyEvent1.class, name = "event-1"),
@JsonSubTypes.Type(value = MyEvent2.class, name = "event-2")
})
private T data;
}
А затем десериализовать с помощью:
String cloudEventJson1 = "{\"eventType\":\"event-1\",\"data\":{\"id\":\"123\",\"details\":\"detail1\"}}";
CloudEvent deserializedEvent1 = objectMapper.readValue(cloudEventJson1, CloudEvent.class); //without subtypes
Все это прекрасно работает.
Но из-за некоторых ограничений я не могу использовать аннотации к классу CloudEvent (обеспечивается внешней зависимостью).
Итак, я настроил ObjectMapper следующим образом:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerSubtypes(new NamedType(MyEvent1.class, "event-1"));
objectMapper.registerSubtypes(new NamedType(MyEvent2.class, "event-2"));
TypeResolverBuilder typeResolverBuilder = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
.init(JsonTypeInfo.Id.NAME, null) //CLASS works
.inclusion(JsonTypeInfo.As.EXTERNAL_PROPERTY)
.typeProperty("eventType")
.typeIdVisibility(true)
// .defaultImpl(Void.class);
objectMapper.setDefaultTyping(typeResolverBuilder);
Но десериализация тем же способом, что и выше, не работает. Он читает eventType
, но не может соответствовать зарегистрированному подтипу.
Я не могу использовать дженерики или TypeReferance при десериализации, потому что мне нужно использовать spring-integration
для чтения событий, которые принимает только основной класс; сопоставление с образцом выполняется вручную после десериализации.
Исключение:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'event-1' as a subtype of [simple type, class java.lang.Object]: known type ids = [] (for POJO property 'data')
at [Source: (String)"{"eventType":"event-1","data":{"id":"123","details":"detail1"}}"; line: 1, column: 271]
Также это настройка ObjectMapper для всех входных классов. Можно ли подключить эти typeResolverBuilder
и subtypes
к CloudEvent.class
(как это делает способ аннотации).