【问题标题】:spring.json.type.mapping property ignored when specifying a custom ObjectMapper指定自定义 ObjectMapper 时忽略 spring.json.type.mapping 属性
【发布时间】:2021-07-21 15:23:57
【问题描述】:

我在将自定义 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__ 标头是用FQCN 设置的,而不是我在spring.json.type.mapping 属性中放入的令牌:foo &gt; com.foo.package.Foo

当我进行调试时,似乎没有调用 org.springframework.kafka.support.serializer.JsonSerializer 类的 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__ 标头设置了正确的标记但正如预期的那样,我使用自定义ObjectMapper 放松了日期格式

那么如何处理这整个情况呢?

【问题讨论】:

    标签: spring jackson spring-kafka


    【解决方案1】:

    如果您自己创建new JsonSerializer&lt;&gt;,则您可以自行为其提供适当的生产者配置。当 serialized 的实例不受 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,但可能我们需要为编程配置案例扩展它...

    【讨论】:

    • 用这条线producerFactory.setValueSerializer(jsonSerializer);我得到了error: incompatible types: JsonSerializer&lt;Object&gt; cannot be converted to Serializer&lt;CAP#1&gt;
    • Required type: Serializer &lt;capture of ?&gt; Provided: JsonSerializer &lt;Object&gt;
    • 这只是一般的 Java 泛型强制问题:DefaultKafkaProducerFactory&lt;?, Object&gt; producerFactoryproducerFactory.setValueSerializer((JsonSerializer) jsonSerializer);。或者您希望通过 producerFactory 生成的显式类型。
    • 感谢您的帮助,我认为如果可以在使用自定义 ObjectMapper 时隐式调用 configure() 方法会很方便
    • 这里有一个问题可以根据您的担忧重新考虑解决方案:github.com/spring-projects/spring-kafka/issues/1879
    猜你喜欢
    • 2019-09-23
    • 2012-03-13
    • 1970-01-01
    • 2019-04-21
    • 2012-01-30
    • 2014-07-10
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多