From 809e3b5e2103a6eb1dacefa32d7917c2dcc3592a Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Wed, 11 Mar 2009 21:46:58 +0000 Subject: [PATCH] Fixed bug 106 by adding custom serialization support for Gregorian Calendar. --- .../com/google/gson/DefaultTypeAdapters.java | 42 ++++++++++++++++ .../functional/DefaultTypeAdaptersTest.java | 49 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java index c16db93f..c9771a87 100644 --- a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java +++ b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java @@ -27,8 +27,10 @@ import java.net.URL; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.GregorianCalendar; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -78,6 +80,8 @@ final class DefaultTypeAdapters { private static final PropertiesCreator PROPERTIES_CREATOR = new PropertiesCreator(); private static final TreeSetCreator TREE_SET_CREATOR = new TreeSetCreator(); + private static final GregorianCalendarTypeAdapter GREGORIAN_CALENDAR_TYPE_ADAPTER = + new GregorianCalendarTypeAdapter(); // The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS // must be defined after the constants for the type adapters. Otherwise, the type adapter @@ -101,6 +105,8 @@ final class DefaultTypeAdapters { map.register(Collection.class, COLLECTION_TYPE_ADAPTER); map.register(Map.class, MAP_TYPE_ADAPTER); map.register(Date.class, DATE_TYPE_ADAPTER); + map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); + map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); map.register(BigDecimal.class, BIG_DECIMAL_TYPE_ADAPTER); map.register(BigInteger.class, BIG_INTEGER_TYPE_ADAPTER); @@ -133,6 +139,8 @@ final class DefaultTypeAdapters { map.register(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER)); map.register(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER)); map.register(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER)); + map.register(Calendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); + map.register(GregorianCalendar.class, GREGORIAN_CALENDAR_TYPE_ADAPTER); map.register(BigDecimal.class, wrapDeserializer(BIG_DECIMAL_TYPE_ADAPTER)); map.register(BigInteger.class, wrapDeserializer(BIG_INTEGER_TYPE_ADAPTER)); @@ -267,6 +275,40 @@ final class DefaultTypeAdapters { } } + private static class GregorianCalendarTypeAdapter implements JsonSerializer, + JsonDeserializer { + + private static final String YEAR = "year"; + private static final String MONTH = "month"; + private static final String DAY_OF_MONTH = "dayOfMonth"; + private static final String HOUR_OF_DAY = "hourOfDay"; + private static final String MINUTE = "minute"; + private static final String SECOND = "second"; + public JsonElement serialize(GregorianCalendar src, Type typeOfSrc, + JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + obj.addProperty(YEAR, src.get(Calendar.YEAR)); + obj.addProperty(MONTH, src.get(Calendar.MONTH)); + obj.addProperty(DAY_OF_MONTH, src.get(Calendar.DAY_OF_MONTH)); + obj.addProperty(HOUR_OF_DAY, src.get(Calendar.HOUR_OF_DAY)); + obj.addProperty(MINUTE, src.get(Calendar.MINUTE)); + obj.addProperty(SECOND, src.get(Calendar.SECOND)); + return obj; + } + + public GregorianCalendar deserialize(JsonElement json, Type typeOfT, + JsonDeserializationContext context) throws JsonParseException { + JsonObject obj = json.getAsJsonObject(); + int year = obj.get(YEAR).getAsInt(); + int month = obj.get(MONTH).getAsInt(); + int dayOfMonth = obj.get(DAY_OF_MONTH).getAsInt(); + int hourOfDay = obj.get(HOUR_OF_DAY).getAsInt(); + int minute = obj.get(MINUTE).getAsInt(); + int second = obj.get(SECOND).getAsInt(); + return new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute, second); + } + } + @SuppressWarnings("unchecked") private static class EnumTypeAdapter> implements JsonSerializer, JsonDeserializer { diff --git a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java index 0bb9e36c..88ca359d 100644 --- a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java +++ b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java @@ -21,7 +21,9 @@ import java.net.URI; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Locale; import java.util.Properties; @@ -217,6 +219,53 @@ public class DefaultTypeAdaptersTest extends TestCase { assertEquals(now.toString(), extracted.toString()); } + public void testDefaultCalendarSerialization() throws Exception { + Gson gson = new GsonBuilder().create(); + String json = gson.toJson(Calendar.getInstance()); + assertTrue(json.contains("year")); + assertTrue(json.contains("month")); + assertTrue(json.contains("dayOfMonth")); + assertTrue(json.contains("hourOfDay")); + assertTrue(json.contains("minute")); + assertTrue(json.contains("second")); + } + + public void testDefaultCalendarDeserialization() throws Exception { + Gson gson = new GsonBuilder().create(); + String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}"; + Calendar cal = gson.fromJson(json, Calendar.class); + assertEquals(2009, cal.get(Calendar.YEAR)); + assertEquals(2, cal.get(Calendar.MONTH)); + assertEquals(11, cal.get(Calendar.DAY_OF_MONTH)); + assertEquals(14, cal.get(Calendar.HOUR_OF_DAY)); + assertEquals(29, cal.get(Calendar.MINUTE)); + assertEquals(23, cal.get(Calendar.SECOND)); + } + + public void testDefaultGregorianCalendarSerialization() throws Exception { + Gson gson = new GsonBuilder().create(); + GregorianCalendar cal = new GregorianCalendar(); + String json = gson.toJson(cal); + assertTrue(json.contains("year")); + assertTrue(json.contains("month")); + assertTrue(json.contains("dayOfMonth")); + assertTrue(json.contains("hourOfDay")); + assertTrue(json.contains("minute")); + assertTrue(json.contains("second")); + } + + public void testDefaultGregorianCalendarDeserialization() throws Exception { + Gson gson = new GsonBuilder().create(); + String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}"; + GregorianCalendar cal = gson.fromJson(json, GregorianCalendar.class); + assertEquals(2009, cal.get(Calendar.YEAR)); + assertEquals(2, cal.get(Calendar.MONTH)); + assertEquals(11, cal.get(Calendar.DAY_OF_MONTH)); + assertEquals(14, cal.get(Calendar.HOUR_OF_DAY)); + assertEquals(29, cal.get(Calendar.MINUTE)); + assertEquals(23, cal.get(Calendar.SECOND)); + } + public void testDateSerializationWithPattern() throws Exception { String pattern = "yyyy-MM-dd"; DateFormat formatter = new SimpleDateFormat(pattern);