Skip to content

Make it easier to configure the JsonDeserializer ObjectMapper without losing the JsonDeserializer configuratin loaded from application.yaml #1703

@jbx1

Description

@jbx1

Currently it is very cumbersome to configure the ObjectMapper of the JsonDeserializer. One would incorrectly assume that the ObjectMapper configuration set through application.yaml such as the following would work:

spring.jackson:
    deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE: false

But it doesn't, for some reason the JsonDeserializer uses its own ObjectMapper ignoring the one configured in the rest of the application. More details seem to be here #680

The only alternative here, as indicated in the documentation, is to define your own JsonDeserializer bean, like this:

@Bean 
Deserializer jsonDeserializer(ObjectMapper objectMapper) {
    return new JsonDeserializer(objectMapper);
}

However this means that the configuration passed through the application.yaml for JsonDeserializer is now lost.

After lots of searching and seeking help here: https://stackoverflow.com/questions/66061869/how-to-make-spring-kafka-jsondeserializer-retain-the-timezone-offset-when-deseri/

thanks to @artembilan the only solution to this is to do something like the following:

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

For some reason the following typesafe way does not work either, which makes things even more confusing:

  @Bean
  ConsumerFactory<String, Object> kafkaConsumerFactory(
      KafkaProperties properties, ObjectMapper objectMapper) {

    Map<String, Object> configs = properties.buildConsumerProperties();
    JsonDeserializer<Object> jsonDeserializer = new JsonDeserializer<>(objectMapper);
    jsonDeserializer.configure(configs, false);

    return new DefaultKafkaConsumerFactory<>(
        properties.buildConsumerProperties(), new StringDeserializer(), jsonDeserializer);
  }

This is not intuitive at all, and difficult to come up with on your own without knowing the internals (apart from the ugly Object generic type).

If it is not possible to use the same ObjectMapper used in the spring context, maybe the right properties for the ObjectMapper can be passed through the spring.kafka.consumer.properties just like the spring.json.value.default.type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions