FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
399 stars 116 forks source link

Deserialization of `LocalDateTime` with `JavaTimeModule` throws exception `MismatchedInput` #186

Closed CapekStanislav closed 3 years ago

CapekStanislav commented 3 years ago

A Simple class for testing:

public class Registration {
    private LocalDateTime date;
}

Construct and calling the serialization and deserialization process:

 private static void serAndDeserLocalDateTime() throws IOException {
        ObjectMapper mapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());

        final Path regPath = Paths.get("registrationObject.json");
        final Registration regObj = new Registration(LocalDateTime.now());

        mapper.writeValue(Files.newBufferedWriter(regPath), regObj);

        final LocalDateTime dateTime = mapper.readValue(Files.newBufferedReader(regPath), LocalDateTime.class);
        System.out.println("dateTime = " + dateTime);
    }

The produced JSON:

{"date":**[2020,10,9,11,12,30,148614900]**} //is a string

When I try to read value from the file exception is thrown: Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Expected array or string. at [Source: (BufferedReader); line: 1, column: 1] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1442) at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1216) at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1148) at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleUnexpectedToken(JSR310DeserializerBase.java:105) at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:155) at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:38) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3218) at cz.stanislavcapek.testing.jackson.Jackson.serAndDeserLocalDateTime(Jackson.java:49) at cz.stanislavcapek.testing.jackson.Jackson.main(Jackson.java:34)

I couldn't find an answer anywhere.

cowtowncoder commented 3 years ago

Which Jackson version? If not 2.11.3, I would suggest trying with that.

CapekStanislav commented 3 years ago

I have used version 2.10.2. I switched to version 2.11.3 but I'm getting the same exception.

cowtowncoder commented 3 years ago

Note to new contributors: I'd accept just failing test case (put under datetime/src/test/.../failing/) as successful contribution (i.e. test-only PR) -- bonus points of course if there is something to fix. Test case can use sample code from above, just replacing file read/write with code that writes value as JSON String, reads that String.

CapekStanislav commented 3 years ago

Problem solved! I wrote a test where I realized that I wasn't deserializing an instance of LocalDateTime but an instance of Registration class.

Thank you for your reply.

(JUnit5)

public class DeserializationLocalDateTimeTest {

    @Test
    void serializationAndDeserializationLocalDateTimeInstance() throws IOException {
        final ObjectMapper mapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());

        final Path path = Paths.get("localDateTime.json");
        final LocalDateTime now = LocalDateTime.now();
        mapper.writeValue(Files.newBufferedWriter(path), now);

        final LocalDateTime localDateTime = mapper.readValue(Files.newBufferedReader(path), LocalDateTime.class);
        System.out.println("localDateTime = " + localDateTime);
       // no exception thrown
    }

    @Test
    void serializationAndDeserializationWrappedLocalDateTimeInstance() throws IOException {
        final ObjectMapper mapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());

        final Path path = Paths.get("wrapperClassLocalDateTime.json");
        final Registration registration = new Registration(LocalDateTime.now());
        mapper.writeValue(Files.newBufferedWriter(path), registration);

        final Registration desRegistration = mapper.readValue(Files.newBufferedReader(path), Registration.class);
        System.out.println("desRegistration = " + desRegistration);
       // no exception thrown
    }
}
cowtowncoder commented 3 years ago

@CapekStanislav ah! Glad you figured it out.