Skip to content

Commit

Permalink
Fix #127 - ZonedDateTime in map keys can now be serialized with zone IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
vetler authored and cowtowncoder committed Oct 6, 2019
1 parent 9532f8f commit ed21550
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;

public class ZonedDateTimeKeySerializer extends JsonSerializer<ZonedDateTime> {
Expand All @@ -20,12 +21,14 @@ private ZonedDateTimeKeySerializer() {
@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException,
JsonProcessingException {
/*
* Serialization of timezone data is unwanted (not ISO). Offset is kept, timezone info is thrown away here.
*
* Keeping timezone info is a new feature which needs to be implemented.
/* [modules-java8#127]: Serialization of timezone data is disabled by default, but can be
* turned on by enabling `SerializationFeature.WRITE_DATES_WITH_ZONE_ID`
*/
gen.writeFieldName(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value));
if (serializers.isEnabled(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)) {
gen.writeFieldName(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(value));
} else {
gen.writeFieldName(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.HashMap;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.MockObjectConfiguration;
import com.fasterxml.jackson.datatype.jsr310.ModuleTestBase;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class WriteZoneIdTest extends ModuleTestBase
{
static class DummyClassWithDate {
Expand All @@ -26,18 +33,47 @@ public DummyClassWithDate(ZonedDateTime date) {
}
}

private static ObjectMapper MAPPER = newMapper();

@Test
public void testSerialization01() throws Exception
{
ZoneId id = ZoneId.of("America/Chicago");
String value = MAPPER.writeValueAsString(id);
assertEquals("The value is not correct.", "\"America/Chicago\"", value);
}

@Test
public void testSerialization02() throws Exception
{
ZoneId id = ZoneId.of("America/Anchorage");
String value = MAPPER.writeValueAsString(id);
assertEquals("The value is not correct.", "\"America/Anchorage\"", value);
}

@Test
public void testSerializationWithTypeInfo01() throws Exception
{
ZoneId id = ZoneId.of("America/Denver");
ObjectMapper mapper = mapperBuilder()
.addMixIn(ZoneId.class, MockObjectConfiguration.class)
.addModule(new JavaTimeModule())
.build();
String value = mapper.writeValueAsString(id);
assertEquals("The value is not correct.", "[\"java.time.ZoneRegion\",\"America/Denver\"]", value);
}

@Test
public void testJacksonAnnotatedPOJOWithDateWithTimezoneToJson() throws Exception
{
ObjectMapper mapper = newMapper();
String ZONE_ID_STR = "Asia/Krasnoyarsk";
final ZoneId ZONE_ID = ZoneId.of(ZONE_ID_STR);

DummyClassWithDate input = new DummyClassWithDate(ZonedDateTime.ofInstant(Instant.ofEpochSecond(0L), ZONE_ID));

// 30-Jun-2016, tatu: Exact time seems to vary a bit based on DST, so let's actually
// just verify appending of timezone id itself:
String json = mapper.writeValueAsString(input);
String json = MAPPER.writeValueAsString(input);
if (!json.contains("\"1970-01-01T")) {
Assert.fail("Should contain time prefix, did not: "+json);
}
Expand All @@ -46,4 +82,16 @@ public void testJacksonAnnotatedPOJOWithDateWithTimezoneToJson() throws Exceptio
Assert.fail("Should contain zone id "+match+", does not: "+json);
}
}

@Test
public void testMapSerialization() throws Exception {
final ZonedDateTime datetime = ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Warsaw]");
final HashMap<ZonedDateTime, String> map = new HashMap<>();
map.put(datetime, "");

String json = MAPPER.writer()
.with(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)
.writeValueAsString(map);
Assert.assertEquals("{\"2007-12-03T10:15:30+01:00[Europe/Warsaw]\":\"\"}", json);
}
}
8 changes: 8 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ Michael O'Keeffe (kupci@github)
* Constributed fix for #114: Prevent deserialization of "" as `null` for `LocalDate`,
`LocalDateTime` in "strict" (non-lenient) mode
(2.10.0)

Michał Żmuda (zmumi@github)
* Reported #127: ZonedDateTime in map keys ignores option to write Zone IDs
(2.10.1)

Vetle Leinonen-Roeim (vetler@github)
* Contributed fix for #127: ZonedDateTime in map keys ignores option to write Zone IDs
(2.10.1)
5 changes: 5 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Modules:
=== Releases ===
------------------------------------------------------------------------

2.10.1 (not yet released)

#127: ZonedDateTime in map keys ignores option to write Zone IDs
(reported by Michał Ż, fixed by Vetle L-R)

2.10.0 (26-Sep-2019)

#51: `YearKeyDeserializer` doesn't work with non-padded year values
Expand Down

0 comments on commit ed21550

Please sign in to comment.