Deserialize millisecond timestamp to java.time.Instant
Solution 1
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);
Solution 2
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.
Solution 3
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.
Solution 4
A more flexible solution could be to write your own convertor class, if you don't want to edit or create an object mapper.
public class LongToInstantConverter extends StdConverter<Long, Instant> {
public Instant convert(final Long value) {
return Instant.ofEpochMilli(value);
}
}
You just need to add the annotation in your class
@JsonDeserialize(converter = LongToInstantConverter.class)
private Instant sentDate;
Marquis Blount
8+ years of professional Software Engineering experience. My preferred language is Java. I've used various different frameworks pertaining to Web, Desktop, and Mobile development. In the near future I want to get more involved with competitive programming.
Updated on June 18, 2022Comments
-
Marquis Blount almost 2 years
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 ofInstant.ofEpochMilli(Long l)
.Is there a way to set the Jackson
ObjectMapper
to use theofEpochMilli
method instead? This is what I currently have for myObjectMapper
: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 as1503115200
theInstant
field is able to set properly.Unfortunately the JSON input must be epoch milliseconds e.g.
1503115200000
.