Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize millisecond timestamp to java.time.Instant

I'm attempting to read a JSON file using Jackson and store one of the fields that is stored as a epoch milliseconds as a Java Instant, however deserialization is not behaving as expected.

Here is what I am seeing when trying to read the timestamp:

1503115200000

Jackson is setting the Instant field as +49601-10-28T16:00:00Z.

This appears to be occurring because Jackson's default is to read the timestamp with Instant.ofEpochSecond(Long l) instead of Instant.ofEpochMilli(Long l).

Is there a way to set the Jackson ObjectMapper to use the ofEpochMilli method instead? This is what I currently have for my ObjectMapper:

ObjectMapper om = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .setSerializationInclusion(Include.NON_NULL);

Note

If I change the input JSON to ISO date such as 2017-08-19T04:00:00Z or to epoch seconds such as 1503115200 the Instant field is able to set properly.

Unfortunately the JSON input must be epoch milliseconds e.g. 1503115200000.

like image 589
Marquis Blount Avatar asked Aug 18 '17 18:08

Marquis Blount


3 Answers

Solution was to add .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false) to the ObjectMapper. Complete ObjectMapper looks like:

ObjectMapper om = new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
            .setSerializationInclusion(Include.NON_NULL);
like image 111
Marquis Blount Avatar answered Nov 13 '22 01:11

Marquis Blount


For those who use Spring Boot and experience this issue during rest request deserialization - provide this in the application.properties:

spring.jackson.deserialization.read-date-timestamps-as-nanoseconds=false

@JB Nizet answer is correct, but since Spring Boot has it's own ObjectMapper inside - you need to configure this value in the properties.

like image 17
Alexander Murza Avatar answered Nov 13 '22 02:11

Alexander Murza


From https://github.com/FasterXML/jackson-modules-java8/blob/master/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.java:

The more ambiguous integer types are read as fractional seconds without a decimal point if {@code READ_DATE_TIMESTAMPS_AS_NANOSECONDS} is enabled (it is by default), and otherwise they are read as milliseconds.

So you need to disable READ_DATE_TIMESTAMPS_AS_NANOSECONDS.

like image 4
JB Nizet Avatar answered Nov 13 '22 01:11

JB Nizet