Kafka JSON Deserializer для интерфейсов - PullRequest
0 голосов
/ 26 декабря 2018

У меня проблема, подобная этой: Kafka Deserialize Nested Generic Types В моем производителе кафки я посылаю объект, который выглядит следующим образом:

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 использовать в десериализации.К сожалению, на стороне слушателя kafka я получаю исключение:

Невозможно создать экземпляр com.api.external.to.IExternalData (не существует создателей, таких как конструкция по умолчанию): абстрактные типы либо должны быть сопоставлены с конкретнымитипов, имеют собственный десериализатор или содержат дополнительную информацию о типах

Потребитель выглядит примерно так:

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

Пожалуйста, помогите решить эту проблему с десериализации.

Ответы [ 2 ]

0 голосов
/ 27 августа 2019

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

ObjectMapper mapper = new ObjectMapper();
// deserializes IExternalData into certain implementation.
mapper.enableDefaultTyping();
0 голосов
/ 23 августа 2019

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

@ JsonDeserialize (as = <<em> Реализация >. Class

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

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