Kafka JSON Deserializer для интерфейсов

У меня проблема, похожая на эту: Kafka десериализует вложенные универсальные типы В моем производителе kafka я отправляю объект, который выглядит так:

public class ExternalTO implements Serializable
{
    private static final long serialVersionUID = 7949808917892350503L;
    private List<IExternalData> externalDatas;

    public ExternalTO()
    {}
}

Краеугольный камень в этом: List<IExternalData> externalDatas.

Этот интерфейс выглядит так:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public interface IExternalData
{
    String getOne();
}

В моем приложении может быть создано несколько типов реализаций интерфейса IExternalBetData (около 10 различных). В этом случае, например, мой производитель сгенерировал ExternalTO с внутренним списком объектов ConcreteExternalData. Отправленный JSON выглядит так:

{
"externalDatas":
[{"@class":"com.api.external.to.ConcreteExternalData",
"one":false,
"two":false}]
}

Поле @class было добавлено из-за аннотации @JsonTypeInfo, и я подумал, что этого достаточно для десериализатора, чтобы «понять», какой тип IExternalData использовать при десериализации. К сожалению, на стороне слушателя кафки я получаю исключение:

Cannot construct instance of com.api.external.to.IExternalData (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

Потребитель похож на:

@Service
public class Consumer
{
    private final ObjectMapper objectMapper;


    public Consumer(ObjectMapper objectMapper)
    {
        this.objectMapper = objectMapper;
    }


    @KafkaListener(topics = {"${kafka.topic}"})
    public void listen(ConsumerRecord<String, String> record)
    {
        objectMapper.readValue(record.value(), ExternalTO.class)
    }

Помогите решить этот вопрос с десериатизацией.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
732
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Из всех реализаций IExternalData десериализатор не знает, в какую из них следует десериализовать данные записи потребителя. Мы должны разрешить эту двусмысленность. Я смог решить эту проблему с помощью аннотации @JsonDeserialize.

@ JsonDeserialize (as = <Выполнение> .class

над объявлением Списка

Ответ принят как подходящий

Решением для меня было установить свойство в objectMapper.

ObjectMapper mapper = new ObjectMapper();
// deserializes IExternalData into certain implementation.
mapper.enableDefaultTyping();

Другие вопросы по теме