spring.json.type.mapping 属性 指定自定义 ObjectMapper 时忽略

spring.json.type.mapping property ignored when specifying a custom ObjectMapper

我在将自定义 ObjectMapper 注入 Spring Kafka 序列化程序时遇到问题,我已通过此 answer 解决了问题,LocalDateTime 正在使用正确的模式进行序列化。

@Configuration
public class KafkaCustomizer implements DefaultKafkaProducerFactoryCustomizer {

    @Bean
    public ObjectMapper objectMapper() {
        var mapper = new ObjectMapper();
        var module = new JavaTimeModule();
        var serializer = new LocalDateTimeSerializer(
                DateTimeFormatter.ofPattern(DateConstants.DATETIME_FORMAT_PATTERN));
        module.addSerializer(LocalDateTime.class, serializer);
        mapper.registerModule(module);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }

    @Override
    public void customize(DefaultKafkaProducerFactory<?, ?> producerFactory) {
        producerFactory.setValueSerializer(new JsonSerializer<>(objectMapper()));
    }

}

但现在我遇到了另一个问题,spring.kafka.producer.properties.spring.json.type.mapping 属性 被忽略了。

我的记录的 __TypeId__ header 是用 FQCN 设置的,而不是用我在 spring.json.type.mapping 属性 中输入的令牌设置的:foo > com.foo.package.Foo

当我调试时,org.springframework.kafka.support.serializer.JsonSerializer class 的 configure 方法似乎没有被调用:

@Override
public void configure(Map<String, ?> configs, boolean isKey) {
    ...
    if (configs.containsKey(TYPE_MAPPINGS) && !this.typeMapperExplicitlySet
            && this.typeMapper instanceof AbstractJavaTypeMapper) {
        ((AbstractJavaTypeMapper) this.typeMapper)
                .setIdClassMapping(createMappings((String) configs.get(TYPE_MAPPINGS)));
    }
}

但是当我禁用自定义时

    @Override
    public void customize(DefaultKafkaProducerFactory<?, ?> producerFactory) {
        // producerFactory.setValueSerializer(new JsonSerializer<>(objectMapper()));
    }

然后 __TypeId__ header 设置了正确的标记 但是正如预期的那样,我使用自定义 ObjectMapper

松开了日期格式

那么如何处理整个情况?

如果您自己做 new JsonSerializer<>,您需要自己为它提供适当的生产者配置。当序列化的实例不受Kafka Client控制时,不会调用configure()

我会说在你的情况下可以这样做:

public void customize(DefaultKafkaProducerFactory<?, ?> producerFactory) {
    JsonSerializer<Object> jsonSerializer = new JsonSerializer<>(objectMapper());
    jsonSerializer.configure(producerFactory.getConfigurationProperties(), false);
    producerFactory.setValueSerializer(jsonSerializer);
}

文档中有一些信息:https://docs.spring.io/spring-kafka/docs/current/reference/html/#tip-json,但可能我们需要针对编程配置案例扩展它...