无法构造java.time.LocalDateTime的实例-Jackson

时间:2019-02-11 17:01:38

标签: java spring java-8 jackson spring-jms

我有两个通过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使它正常工作?

2 个答案:

答案 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会选择它。