Use the date format for java.sql.Date and java.sql.Timestamp.

Fixes issue 230.
This commit is contained in:
Jesse Wilson 2011-03-29 21:36:19 +00:00
parent 4efb133b4a
commit f718784f33
3 changed files with 82 additions and 19 deletions

View File

@ -17,7 +17,6 @@
package com.google.gson;
import com.google.gson.internal.$Types;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@ -301,6 +300,10 @@ final class DefaultTypeAdapters {
return DEFAULT_INSTANCE_CREATORS;
}
/**
* This type adapter supports three subclasses of date: Date, Timestamp, and
* java.sql.Date.
*/
static final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
private final DateFormat enUsFormat;
private final DateFormat localFormat;
@ -345,6 +348,19 @@ final class DefaultTypeAdapters {
if (!(json instanceof JsonPrimitive)) {
throw new JsonParseException("The date should be a string value");
}
Date date = deserializeToDate(json);
if (typeOfT == Date.class) {
return date;
} else if (typeOfT == Timestamp.class) {
return new Timestamp(date.getTime());
} else if (typeOfT == java.sql.Date.class) {
return new java.sql.Date(date.getTime());
} else {
throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT);
}
}
private Date deserializeToDate(JsonElement json) {
synchronized (localFormat) {
try {
return localFormat.parse(json.getAsString());

View File

@ -18,6 +18,7 @@ package com.google.gson;
import com.google.gson.internal.$Preconditions;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
@ -400,6 +401,9 @@ public final class GsonBuilder {
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
* java.sql.Timestamp} and {@link java.sql.Date}.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
* valid date and time patterns.</p>
@ -679,12 +683,19 @@ public final class GsonBuilder {
}
if (dateTypeAdapter != null) {
if (!serializers.hasSpecificHandlerFor(Date.class)) {
serializers.register(Date.class, dateTypeAdapter);
}
if (!deserializers.hasSpecificHandlerFor(Date.class)) {
deserializers.register(Date.class, dateTypeAdapter);
}
registerIfAbsent(Date.class, serializers, dateTypeAdapter);
registerIfAbsent(Date.class, deserializers, dateTypeAdapter);
registerIfAbsent(Timestamp.class, serializers, dateTypeAdapter);
registerIfAbsent(Timestamp.class, deserializers, dateTypeAdapter);
registerIfAbsent(java.sql.Date.class, serializers, dateTypeAdapter);
registerIfAbsent(java.sql.Date.class, deserializers, dateTypeAdapter);
}
}
private static <T> void registerIfAbsent(Class<?> type,
ParameterizedTypeHandlerMap<T> adapters, T adapter) {
if (!adapters.hasSpecificHandlerFor(type)) {
adapters.register(type, adapter);
}
}
}

View File

@ -15,6 +15,13 @@
*/
package com.google.gson.functional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -36,17 +43,8 @@ import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.UUID;
import junit.framework.TestCase;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
/**
* Functional test for Json serialization and deserialization for common classes for which default
* support is provided in Gson. The tests for Map types are available in {@link MapTest}.
@ -380,15 +378,53 @@ public class DefaultTypeAdaptersTest extends TestCase {
// http://code.google.com/p/google-gson/issues/detail?id=230
public void testDateSerializationInCollection() throws Exception {
Type listOfDates = new TypeToken<List<Date>>() {}.getType();
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
List<Date> dates = Arrays.asList(new Date(0));
String json = gson.toJson(dates, new TypeToken<List<Date>>() {}.getType());
assertEquals("[\"1969-12-31\"]", json);
String json = gson.toJson(dates, listOfDates);
assertEquals("[\"1970-01-01\"]", json);
assertEquals(0L, gson.<List<Date>>fromJson("[\"1970-01-01\"]", listOfDates).get(0).getTime());
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
}
}
// http://code.google.com/p/google-gson/issues/detail?id=230
public void testTimestampSerialization() throws Exception {
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
Timestamp timestamp = new Timestamp(0L);
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
String json = gson.toJson(timestamp, Timestamp.class);
assertEquals("\"1970-01-01\"", json);
assertEquals(0, gson.fromJson("\"1970-01-01\"", Timestamp.class).getTime());
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
}
}
// http://code.google.com/p/google-gson/issues/detail?id=230
public void testSqlDateSerialization() throws Exception {
TimeZone defaultTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
java.sql.Date sqlDate = new java.sql.Date(0L);
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
String json = gson.toJson(sqlDate, Timestamp.class);
assertEquals("\"1970-01-01\"", json);
assertEquals(0, gson.fromJson("\"1970-01-01\"", java.sql.Date.class).getTime());
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);