我有两个通过JMS消息传递和ActiveMQ进行通信的Spring Boot应用程序。
一个应用程序向另一个应用程序发送一个包含LocalDateTime属性的对象。该对象被序列化为JSON,以便发送给其他应用程序。
我面临的问题是,杰克逊在尝试将传入的json映射到我的对象时,无法对LocalDateTime属性进行反序列化。到达“侦听器应用程序”时,LocalDateTime属性具有以下格式:
"lastSeen":{
"nano":0,
"year":2019,
"monthValue":4,
"dayOfMonth":8,
"hour":15,
"minute":6,
"second":0,
"month":"APRIL",
"dayOfWeek":"MONDAY",
"dayOfYear":98,
"chronology":{
"id":"ISO",
"calendarType":"iso8601"
}
}
我得到的异常如下:
org.springframework.jms.support.converter.MessageConversionException: Failed to convert JSON message content; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.LocalDateTime
通过使用以下注释,我能够暂时解决此问题:
@JsonSerialize(as = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class, as = LocalDateTime.class)
private LocalDateTime lastSeen;
但它们属于jackson datatype jsr310,现在已已弃用。
是否有任何方法/替代方法可以不使用上述注释反序列化此LocalDateTime属性?或者如何使用推荐的jackson-modules-java8使它正常工作?
答案 0 :(得分:0)
您编写的解决方案是正确的方法。 下面提到其他方法。 公共类LocalDateTimeSerializer实现JsonSerializer { @Override 公共JsonElement serialize(LocalDateTime localDateTime,Type type,JsonSerializationContext jsonSerializationContext){ 即时即时= localDateTime.atZone(ZoneId.systemDefault())。toInstant(); Date date = Date.from(instant); 返回新的JsonPrimitive(date.getTime()); } }
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer());
Gson gson = gsonBuilder.create();
另一种方法。 可以尝试一下。 尝试将日期时间格式更改为字符串。 “ 2011-04-08T09:00:00”。 nano和其他格式是如此复杂,我无法从您的lastseen json看出您确切在说什么日期时间。它还会错过时区,因此您的本地时间可以在部署解决方案的任何地方。如果在3个不同的时区中进行部署,则本地时间不正确。 使用此字符串格式或自行创建 “ 2011-04-08T09:00:00”
public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
@Override
public Date deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String date = jsonParser.getText();
try {
return format.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
@JsonDeserialize(using = CustomJsonDateDeserializer.class)
答案 1 :(得分:0)
我记得较早版本的spring没有这个问题(或者我很幸运) 但这是我在Spring Boot 2.1.7.RELEASE中解决的方法:
首先,添加Jackson's support modules以支持Java 8功能(TimeDate API)
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
然后在Spring中使用自定义配置(支持Java 8)注册一个默认的ObjectMapper bean。
@Bean
@Primary
public ObjectMapper geObjMapper(){
return new ObjectMapper()
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
}
注意:@Primary用作预防措施,因此,如果在类路径上还有其他ObjectsMapper Bean,则默认情况下,spring会选择它。