From 6a98cf9d8780ac7e6e9ce4284e9dc0a2dd891ec9 Mon Sep 17 00:00:00 2001 From: Robert Zwerus Date: Wed, 23 Mar 2016 14:50:01 +0100 Subject: [PATCH] Handle JSON serialized Dates from JavaScript in LocalDateTimeDeserializer --- .../deser/LocalDateTimeDeserializer.java | 18 +++++++++++++++++- .../jsr310/TestLocalDateTimeSerialization.java | 14 +++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserializer.java b/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserializer.java index 8350d901..3eeae76c 100644 --- a/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserializer.java @@ -18,7 +18,9 @@ import java.io.IOException; import java.time.DateTimeException; +import java.time.Instant; import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import com.fasterxml.jackson.core.JsonParser; @@ -40,10 +42,12 @@ public class LocalDateTimeDeserializer { private static final long serialVersionUID = 1L; + private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer(); private LocalDateTimeDeserializer() { - this(DateTimeFormatter.ISO_LOCAL_DATE_TIME); + this(DEFAULT_FORMATTER); } public LocalDateTimeDeserializer(DateTimeFormatter formatter) { @@ -63,7 +67,19 @@ public LocalDateTime deserialize(JsonParser parser, DeserializationContext conte if (string.length() == 0) { return null; } + try { + if (_formatter == DEFAULT_FORMATTER) { + // JavaScript by default includes time and zone in JSON serialized Dates (UTC/ISO instant format). + if (string.length() > 10 && string.charAt(10) == 'T') { + if (string.endsWith("Z")) { + return LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC); + } else { + return LocalDateTime.parse(string, DEFAULT_FORMATTER); + } + } + } + return LocalDateTime.parse(string, _formatter); } catch (DateTimeException e) { _rethrowDateTimeException(parser, e); diff --git a/src/test/java/com/fasterxml/jackson/datatype/jsr310/TestLocalDateTimeSerialization.java b/src/test/java/com/fasterxml/jackson/datatype/jsr310/TestLocalDateTimeSerialization.java index cfab9dae..bad64d20 100644 --- a/src/test/java/com/fasterxml/jackson/datatype/jsr310/TestLocalDateTimeSerialization.java +++ b/src/test/java/com/fasterxml/jackson/datatype/jsr310/TestLocalDateTimeSerialization.java @@ -24,8 +24,10 @@ import org.junit.Before; import org.junit.Test; +import java.time.Instant; import java.time.LocalDateTime; import java.time.Month; +import java.time.ZoneOffset; import java.time.temporal.Temporal; import java.util.Calendar; import java.util.Date; @@ -314,13 +316,23 @@ public void testDeserializationAsString03() throws Exception assertEquals("The value is not correct.", time, value); } + @Test + public void testDeserializationAsString04() throws Exception + { + Instant instant = Instant.now(); + LocalDateTime value = mapper.readValue('"' + instant.toString() + '"', LocalDateTime.class); + + assertNotNull("The value should not be null.", value); + assertEquals("The value is not correct.", LocalDateTime.ofInstant(instant, ZoneOffset.UTC), value); + } + @Test public void testDeserializationWithTypeInfo01() throws Exception { LocalDateTime time = LocalDateTime.of(2005, Month.NOVEMBER, 5, 22, 31, 5, 829837); final ObjectMapper m = newMapper().addMixIn(Temporal.class, MockObjectConfiguration.class); - + m.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true); Temporal value = m.readValue( "[\"" + LocalDateTime.class.getName() + "\",[2005,11,5,22,31,5,829837]]", Temporal.class