Fixed issue 53 where default date instances were not getting

serialized/deserialized properly. Added support for time style as well by using he default formatter that uses time style.
This commit is contained in:
Inderjeet Singh 2008-10-13 18:40:20 +00:00
parent 4d73459b7e
commit 2b9fd47b72
4 changed files with 56 additions and 14 deletions

View File

@ -52,7 +52,7 @@ import java.util.TreeSet;
final class DefaultTypeAdapters {
private static final DefaultDateTypeAdapter DATE_TYPE_ADAPTER =
new DefaultDateTypeAdapter(DateFormat.DEFAULT);
new DefaultDateTypeAdapter(DateFormat.getDateTimeInstance());
@SuppressWarnings("unchecked")
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
private static final UrlTypeAdapter URL_TYPE_ADAPTER = new UrlTypeAdapter();
@ -169,11 +169,19 @@ final class DefaultTypeAdapters {
public DefaultDateTypeAdapter(String datePattern) {
this.format = new SimpleDateFormat(datePattern);
}
DefaultDateTypeAdapter(DateFormat format) {
this.format = format;
}
public DefaultDateTypeAdapter(int style) {
this.format = DateFormat.getDateInstance(style);
}
public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
this.format = DateFormat.getDateTimeInstance(dateStyle, timeStyle);
}
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
String dateFormatAsString = format.format(src);
return new JsonPrimitive(dateFormatAsString);

View File

@ -117,7 +117,8 @@ public final class Gson {
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
* to change the default representation, you can do so by registering a type adapter through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. You can change
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
* ignores the millisecond portion of the date during serialization. You can change
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
* {@link GsonBuilder#setDateFormat(String)}. </li>
* <li>By default, Gson ignores the {@link com.google.gson.annotations.Expose} annotation.

View File

@ -64,6 +64,7 @@ public final class GsonBuilder {
private boolean serializeNulls;
private String datePattern;
private int dateStyle;
private int timeStyle;
/**
* Creates a GsonBuilder instance that can be used to build Gson with various configuration
@ -85,6 +86,7 @@ public final class GsonBuilder {
deserializers = new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
serializeNulls = false;
dateStyle = DateFormat.DEFAULT;
timeStyle = DateFormat.DEFAULT;
}
/**
@ -225,6 +227,28 @@ public final class GsonBuilder {
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @param timeStyle the predefined style for the time portion of the date objects
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.datePattern = null;
return this;
}
/**
* Configures Gson for custom serialization or deserialization. This method combines the
* registration of an {@link InstanceCreator}, {@link JsonSerializer}, and a
@ -323,7 +347,8 @@ public final class GsonBuilder {
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
addTypeAdaptersForDate(datePattern, dateStyle, customSerializers, customDeserializers);
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers);
customSerializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_SERIALIZERS);
customDeserializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_DESERIALIZERS);
@ -337,15 +362,15 @@ public final class GsonBuilder {
return gson;
}
private static void addTypeAdaptersForDate(String datePattern, int dateStyle,
private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) {
// NOTE: if a date pattern exists, then that style takes priority
DefaultDateTypeAdapter dateTypeAdapter = null;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
}
if (dateTypeAdapter != null
&& !serializers.hasAnyHandlerFor(Date.class)

View File

@ -187,44 +187,52 @@ public class DefaultTypeAdaptersTest extends TestCase {
public void testDefaultDateSerialization() {
Date now = new Date();
String json = gson.toJson(now);
assertEquals("\"" + DateFormat.getDateInstance().format(now) + "\"", json);
assertEquals("\"" + DateFormat.getDateTimeInstance().format(now) + "\"", json);
}
public void testDefaultDateDeserialization() {
Date date = new Date();
assertEquals(date, gson.fromJson(gson.toJson(date), Date.class));
String json = gson.toJson(date);
Date extracted = gson.fromJson(json, Date.class);
// Using comparison of string forms since the extracted date has lost the millisecond portion.
assertEquals(date.toString(), extracted.toString());
}
public void testDefaultDateSerializationUsingBuilder() throws Exception {
Gson gson = new GsonBuilder().create();
Date now = new Date();
String json = gson.toJson(now);
assertEquals("\"" + DateFormat.getDateInstance().format(now) + "\"", json);
assertEquals("\"" + DateFormat.getDateTimeInstance().format(now) + "\"", json);
}
public void testDefaultDateDeserializationUsingBuilder() throws Exception {
Gson gson = new GsonBuilder().create();
Date now = new Date();
String json = gson.toJson(now);
assertEquals(now, gson.fromJson(json, Date.class));
Date extracted = gson.fromJson(json, Date.class);
assertEquals(now.toString(), extracted.toString());
}
public void testDateSerializationWithPattern() throws Exception {
String pattern = "yyyy-MM-dd";
DateFormat formatter = new SimpleDateFormat(pattern);
Gson gson = new GsonBuilder().setDateFormat(DateFormat.LONG).setDateFormat(pattern).create();
Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL).setDateFormat(pattern).create();
Date now = new Date();
String json = gson.toJson(now);
assertEquals("\"" + formatter.format(now) + "\"", json);
}
@SuppressWarnings("deprecation")
public void testDateDeserializationWithPattern() throws Exception {
String pattern = "yyyy-MM-dd";
DateFormat formatter = new SimpleDateFormat(pattern);
Gson gson = new GsonBuilder().setDateFormat(DateFormat.LONG).setDateFormat(pattern).create();
Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL).setDateFormat(pattern).create();
Date now = new Date();
String json = gson.toJson(now);
assertEquals(now, gson.fromJson(json, Date.class));
Date extracted = gson.fromJson(json, Date.class);
assertEquals(now.getYear(), extracted.getYear());
assertEquals(now.getMonth(), extracted.getMonth());
assertEquals(now.getDay(), extracted.getDay());
}
private static class ClassWithBigDecimal {