如何覆盖 Spring Cloud Stream 的 Jackson ObjectMapper 配置?
How to override Jackson ObjectMapper configuration for Spring Cloud Stream?
在 Spring Boot/Spring Cloud Stream 应用程序中,我们使用的是 Kafka 活页夹。我注意到,在反序列化包含 ZonedDateTime
属性 的 Kafka 消息时,Jackson 会自动更改时区(到 UTC),即使序列化形式包含时区(例如,20210101084239+0200
).
经过一些研究,我发现这是一个可以禁用的默认反序列化功能,因此我在 @Configuration
类:
之一中添加了以下内容
@Bean
public Jackson2ObjectMapperBuilderCustomizer objectMapperCustomizer() {
return builder -> {
builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
//... other custom config...
};
但这不起作用,大概是因为 Spring Cloud Stream(或 Kafka 绑定程序)使用的 ObjectMapper 不是从应用程序上下文中配置的 Jackson2ObjectMapperBuilder
构建的:-( .
经过更多研究,我发现有人声称有必要覆盖 Spring 消息的 MappingJackson2MessageConverter
,因为它创建了自己的 ObjectMapper
。所以我添加了这个:
@Bean
public MappingJackson2MessageConverter springMessagingJacksonConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.getObjectMapper().configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
return converter;
}
不幸的是,这仍然没有用。我仍然在忽略 JSON 值中的时区信息而反序列化 ZonedDateTime
个对象。
那么什么 bean 创建了 Spring Cloud Stream Kafka binder 使用的 ObjectMapper
,我如何自定义它的配置?
If you want to replace the default ObjectMapper completely, either define a @Bean of that type and mark it as @Primary or, if you prefer the builder-based approach, define a Jackson2ObjectMapperBuilder @Bean. Note that, in either case, doing so disables all auto-configuration of the ObjectMapper.
如以下讨论评论和 here 中所述,Spring Cloud Stream 中存在一个错误,它没有使用 Spring 应用程序上下文中的 ObjectMapper
它应该的地方。
话虽如此,解决方法是定义您自己的 Serde<>
@Bean,它调用采用 ObjectMapper
的 JsonSerde<>
构造函数,后者是从应用程序上下文中注入的。例如:
@Configuration
public class MyConfig {
@Bean
public Serde<SomeClass> someClassSerde(ObjectMapper jsonMapper) {
return new JsonSerde<SomeClass>(SomeClass.class, jsonMapper);
}
}
此解决方法的不利之处在于,您必须对要在消息中 serialize/deserialize 的每个目标类型执行此操作。
在 Spring Boot/Spring Cloud Stream 应用程序中,我们使用的是 Kafka 活页夹。我注意到,在反序列化包含 ZonedDateTime
属性 的 Kafka 消息时,Jackson 会自动更改时区(到 UTC),即使序列化形式包含时区(例如,20210101084239+0200
).
经过一些研究,我发现这是一个可以禁用的默认反序列化功能,因此我在 @Configuration
类:
@Bean
public Jackson2ObjectMapperBuilderCustomizer objectMapperCustomizer() {
return builder -> {
builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
//... other custom config...
};
但这不起作用,大概是因为 Spring Cloud Stream(或 Kafka 绑定程序)使用的 ObjectMapper 不是从应用程序上下文中配置的 Jackson2ObjectMapperBuilder
构建的:-( .
经过更多研究,我发现有人声称有必要覆盖 Spring 消息的 MappingJackson2MessageConverter
,因为它创建了自己的 ObjectMapper
。所以我添加了这个:
@Bean
public MappingJackson2MessageConverter springMessagingJacksonConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.getObjectMapper().configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
return converter;
}
不幸的是,这仍然没有用。我仍然在忽略 JSON 值中的时区信息而反序列化 ZonedDateTime
个对象。
那么什么 bean 创建了 Spring Cloud Stream Kafka binder 使用的 ObjectMapper
,我如何自定义它的配置?
If you want to replace the default ObjectMapper completely, either define a @Bean of that type and mark it as @Primary or, if you prefer the builder-based approach, define a Jackson2ObjectMapperBuilder @Bean. Note that, in either case, doing so disables all auto-configuration of the ObjectMapper.
如以下讨论评论和 here 中所述,Spring Cloud Stream 中存在一个错误,它没有使用 Spring 应用程序上下文中的 ObjectMapper
它应该的地方。
话虽如此,解决方法是定义您自己的 Serde<>
@Bean,它调用采用 ObjectMapper
的 JsonSerde<>
构造函数,后者是从应用程序上下文中注入的。例如:
@Configuration
public class MyConfig {
@Bean
public Serde<SomeClass> someClassSerde(ObjectMapper jsonMapper) {
return new JsonSerde<SomeClass>(SomeClass.class, jsonMapper);
}
}
此解决方法的不利之处在于,您必须对要在消息中 serialize/deserialize 的每个目标类型执行此操作。