Как заставить Spring Kafka JsonDeserializer сохранять смещение часового пояса при десериализации в OffsetDateTime

У меня есть сообщение, полученное через Kafka, в котором, как я знаю, указан часовой пояс, отличный от UTC. Когда я использую org.apache.kafka.common.serialization.StringDeserializer чтобы проверить это, я получаю правильную временную метку в формате ISO 8601 с часовым поясом:

      {  "id": "e499f2e8-a50e-4ff8-a9fe-0eaf9d3314bf", "sent_ts": "2021-02-04T14:06:10+01:00" }

Когда я переключаюсь на org.springframework.kafka.support.serializer.JsonDeserializerэто потеряно. Мой POJO выглядит так:

      public class MyMessage {

    @JsonProperty("id")
    private String id;

    @JsonProperty("sent_ts")
    private OffsetDateTime sentTs;

    @Override
    public String toString() {
        return "MyMessage{" +
                "id='" + id + '\'' +
                ", sentTs=" + sentTs +
                '}';
}

Когда я регистрирую полученное сообщение, я получаю:

      MyMessage{id='e499f2e8-a50e-4ff8-a9fe-0eaf9d3314bf', sentTs=2021-02-04T13:06:10Z}

Я думал, что, должно быть, использовал Джексона, поэтому в моем application.yml конфигурацию я установил:

      spring.jackson:
    deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE: false

Это не сработало. Еще попробовал настроить настройщик:

      @Configuration
public class ObjectMapperBuilderCustomizer implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder builder) {
        builder.modules(new JavaTimeModule());
        builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
    }
}

Что тоже не сработало.

Я подумал, может быть, это должно быть свойство потребителя Kafka, поэтому я также попробовал:

      spring:
    consumer:
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      properties:
        spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE: false

По-прежнему не работает.

Есть ли способ сделать JsonDeserializer работать правильно и сохранять правильное смещение часового пояса?

1 ответ

Решение

Когда тебе это нравится value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer, экземпляр этого класса создается клиентским кодом Apache Kafka, который полностью не знает конфигурации Spring.

Если вы хотите полагаться на настройки Spring Boot и свои настройки, вам следует подумать о том, чтобы сделать что-то вроде этого:

      @Bean
DefaultKafkaConsumerFactory kafkaConsumerFactory(KafkaProperties properties, ObjectMapper objectMapper) {
   Map<String, Object> consumerProperties = properties.buildConsumerProperties();
   JsonDeserializer<Object> jsonDeserializer = new JsonDeserializer<>(objectMapper);
   jsonDeserializer.configure(consumerProperties, false);

   return new DefaultKafkaConsumerFactory(consumerProperties, 
                   new StringDeserializer(), jsonDeserializer);
}

Обратите внимание, как я звоню jsonDeserializer.configure(consumerProperties, false);. Таким образом, вы по-прежнему сможете настроить остальные свойства для потребителя Kafka в applicaiton.yml.

Пожалуйста, подумайте о том, чтобы поднять проблему GH для Spring Boot, поэтому мы пересмотрим, как мы будем работать с JsonDeserializer и автоматически настраивается ObjectMapper для улучшения взаимодействия с конечным пользователем на сервере.

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