Cannot construct instance of java.time.LocalDateTime - Jackson

12,962

Solution 1

I remember I did not have this problem with older versions of spring (or maybe I was LUCKY) But this is how I solved it in Spring boot 2.1.7.RELEASE:

First, add Jackson's support modules in order to support Java 8 features (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>

Then register a default ObjectMapper bean with custom configurations (to support Java 8) in the Spring.

@Bean
@Primary
public ObjectMapper geObjMapper(){
    return new ObjectMapper()
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JavaTimeModule());
}

NOTE: @Primary is used as a precautionary measure, so if there are other ObjectsMapper beans on the class-path, the spring will pick this one by default.

Solution 2

The solution you wrote is right approach. Other approaches are mentioned below. public class LocalDateTimeSerializer implements JsonSerializer { @Override public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext jsonSerializationContext) { Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date date = Date.from(instant); return new JsonPrimitive(date.getTime()); } }

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer());

Gson gson = gsonBuilder.create();

Another approach. Any way try this . try to change date time format to string. "2011-04-08T09:00:00". The nano and other format are so complex I cannot tell from your lastseen json what datetime exactly you are talking about. It misses Time zone too so your local time can be anywhere you deploy solution,If you deploy in 3 different time zone machines local time is not correct. Use this string format or make your own "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)
Share:
12,962
Daniel Castillo
Author by

Daniel Castillo

Updated on June 11, 2022

Comments

  • Daniel Castillo
    Daniel Castillo almost 2 years

    I have two Spring Boot applications which communicate through JMS Messaging and ActiveMQ.

    One app sends to the other app an object which contains a LocalDateTime property. This object is serialized to JSON in order to be sent to the other application.

    The problem I'm facing is that Jackson is not able to deserialize the LocalDateTime property when it's trying to map the incoming json to my object. The LocalDateTime property has the following format when it arrives to the "listener app":

    "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"
      }
    }
    

    The exception I'm getting is the following:

    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

    I was able to fix this issue temporarily by using the following annotations:

    @JsonSerialize(as = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class, as = LocalDateTime.class)
    private LocalDateTime lastSeen;
    

    but they belong to jackson datatype jsr310 which is now DEPRECATED.

    Is there any way/alternative to deserialize this LocalDateTime property without using the above annotations? Or how do I get this to work using the recommended jackson-modules-java8?