Jackson deserialize elasticsearch long as LocalDateTime with Java 8
To build LocalDateTime
from milliseconds from the epoch of 1970-01-01T00:00:00Z
we need a time zone. In version 2.9.9 it throws exception when milliseconds appears:
raw timestamp (1563448935000) not allowed for
java.time.LocalDateTime
: need additional information such as an offset or time-zone (see class Javadocs)
But we can implement our deserialiser which will try to do this with default time zone. Example implementation could look like below:
class MillisOrLocalDateTimeDeserializer extends LocalDateTimeDeserializer { public MillisOrLocalDateTimeDeserializer() { super(DateTimeFormatter.ISO_LOCAL_DATE_TIME); } @Override public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException { if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) { long value = parser.getValueAsLong(); Instant instant = Instant.ofEpochMilli(value); return LocalDateTime.ofInstant(instant, ZoneOffset.UTC); } return super.deserialize(parser, context); }}
ZoneOffset.UTC
is used. In your case you can provide yours or use system default. Example usage:
import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;import java.io.IOException;import java.time.Instant;import java.time.LocalDateTime;import java.time.ZoneOffset;import java.time.format.DateTimeFormatter;public class JsonApp { public static void main(String[] args) throws Exception { JavaTimeModule javaTimeModule = new JavaTimeModule(); // override default javaTimeModule.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer()); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(javaTimeModule); String json = "{\"created\":1563448935000}"; System.out.println(mapper.readValue(json, Created.class)); }}class Created { private LocalDateTime created; // getters, setters, toString}
Above code prints:
Created{created=2019-07-18T11:22:15}
EDIT: Using Jackson 2.9.0
, because of this issue the code provided will not be invoked since findAndRegisterModules
which is called AFTER registering the customized module will override it. Removing that call will make the full scenario work. If above will not work for your version, you need to debug default implementation and find a reason.
Use Instant
as a Jackson field type for dates. This simplifies everything!All you will need is only register module: https://github.com/FasterXML/jackson-modules-java8