我正在努力配置要由Spring Integration DSL转换器使用的“自定义” ObjectMapper。我收到了java.time.Instant我想解析为对象属性的json表示形式。即: {“ type”:“ TEST”,“ source”:“ TEST”,“ timestamp”:{“ epochSecond”:1454503381,“ nano”:335000000}}
java.time.Instant
该消息是一个kafka消息,引发了一个问题:我是否应该编写一个实现Kafka编码器/解码器的自定义序列化程序,以便能够将kafka消息转换为正确的对象,或者spring- integration必须自动执行此操作?
固件/依赖关系和版本:Spring Boot-1.3.2.RELEASE Spring Integration Java Dsl-1.1.1.RELEASE FasterXml Jackson-2.6.5
我已根据Jackson文档将此Java配置添加到项目中:https : //github.com/FasterXML/jackson-datatype- jsr310
@Configuration public class IntegrationConfiguration { @Bean public JsonObjectMapper<JsonNode, JsonParser> jsonObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); return new Jackson2JsonObjectMapper(mapper); } }
以及以下Jackson JSR-310人工制品:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.6.5</version> </dependency>
根据Spring博客上的这篇文章,我什至不必注册新的Java8时间模块。 https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in- spring#jackson-modules
这是我得到的例外:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class java.time.Instant]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: {"type":"TEST","source":"TEST","timestamp":{"epochSecond":1454503381,"nano":335000000}}; line: 1, column: 71] (through reference chain: my.app.MyDto["timestamp"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2764) at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:75) at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:44) at org.springframework.integration.support.json.AbstractJacksonJsonObjectMapper.fromJson(AbstractJacksonJsonObjectMapper.java:56) at org.springframework.integration.json.JsonToObjectTransformer.doTransform(JsonToObjectTransformer.java:78) at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33) ... 74 more
解决方案: 问题是我希望Spring能够检测到jackson-datatype- jsr310原型并注册JavaTimeModule,但事实并非如此。有两种方法可以解决此问题: 1.如果我们将Spring Boot与Spring Integration一起使用,则可以接受。 2.如果使用Spring Integration Dsl,只需将IntegrationConfiguration类与jsonObjectMapper()bean一起使用,并像这样使用它:
@Autowired private JsonObjectMapper jsonObjectMapper; return IntegrationFlows .from(inboundChannel()) .transform(Transformers.fromJson(myDto.class, jsonObjectMapper)) ...
与Spring Boot无关,它没有强制Spring Integration使用它。
你只需要配置JsonToObjectTransformer与您jsonObjetMapper():
JsonToObjectTransformer
jsonObjetMapper()
@Bean @Transformer(inputChannel="input", outputChannel="output") JsonToObjectTransformer jsonToObjectTransformer() { return new JsonToObjectTransformer(jsonObjectMapper()); }
尽管没有理由注册JsonObjectMapper为bean。
JsonObjectMapper