Merge pull request #1707 from Marcono1234/optional-sql

Make dependency on java.sql optional
This commit is contained in:
Éamonn McManus 2021-08-25 11:26:58 -07:00 committed by GitHub
commit 1023f0fe34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 442 additions and 235 deletions

View File

@ -49,9 +49,8 @@ import com.google.gson.internal.bind.JsonTreeWriter;
import com.google.gson.internal.bind.MapTypeAdapterFactory;
import com.google.gson.internal.bind.ObjectTypeAdapter;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import com.google.gson.internal.bind.SqlDateTypeAdapter;
import com.google.gson.internal.bind.TimeTypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.internal.sql.SqlTypesSupport;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
@ -262,9 +261,13 @@ public final class Gson {
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
if (SqlTypesSupport.SUPPORTS_SQL_TYPES) {
factories.add(SqlTypesSupport.TIME_FACTORY);
factories.add(SqlTypesSupport.DATE_FACTORY);
factories.add(SqlTypesSupport.TIMESTAMP_FACTORY);
}
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
@ -28,8 +27,10 @@ import java.util.Map;
import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.Excluder;
import com.google.gson.internal.bind.DefaultDateTypeAdapter;
import com.google.gson.internal.bind.TreeTypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.internal.sql.SqlTypesSupport;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
@ -417,8 +418,8 @@ 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>The date format will be used to serialize and deserialize {@link java.util.Date} and in case
* the {@code java.sql} module is present, also {@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
@ -602,26 +603,35 @@ public final class GsonBuilder {
this.factories, this.hierarchyFactories, factories);
}
@SuppressWarnings("unchecked")
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
List<TypeAdapterFactory> factories) {
DefaultDateTypeAdapter dateTypeAdapter;
TypeAdapter<Timestamp> timestampTypeAdapter;
TypeAdapter<java.sql.Date> javaSqlDateTypeAdapter;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, datePattern);
timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, datePattern);
javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, datePattern);
TypeAdapterFactory dateAdapterFactory;
boolean sqlTypesSupported = SqlTypesSupport.SUPPORTS_SQL_TYPES;
TypeAdapterFactory sqlTimestampAdapterFactory = null;
TypeAdapterFactory sqlDateAdapterFactory = null;
if (datePattern != null && !datePattern.trim().isEmpty()) {
dateAdapterFactory = DefaultDateTypeAdapter.DateType.DATE.createAdapterFactory(datePattern);
if (sqlTypesSupported) {
sqlTimestampAdapterFactory = SqlTypesSupport.TIMESTAMP_DATE_TYPE.createAdapterFactory(datePattern);
sqlDateAdapterFactory = SqlTypesSupport.DATE_DATE_TYPE.createAdapterFactory(datePattern);
}
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, dateStyle, timeStyle);
timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, dateStyle, timeStyle);
javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, dateStyle, timeStyle);
dateAdapterFactory = DefaultDateTypeAdapter.DateType.DATE.createAdapterFactory(dateStyle, timeStyle);
if (sqlTypesSupported) {
sqlTimestampAdapterFactory = SqlTypesSupport.TIMESTAMP_DATE_TYPE.createAdapterFactory(dateStyle, timeStyle);
sqlDateAdapterFactory = SqlTypesSupport.DATE_DATE_TYPE.createAdapterFactory(dateStyle, timeStyle);
}
} else {
return;
}
factories.add(TypeAdapters.newFactory(Date.class, dateTypeAdapter));
factories.add(TypeAdapters.newFactory(Timestamp.class, timestampTypeAdapter));
factories.add(TypeAdapters.newFactory(java.sql.Date.class, javaSqlDateTypeAdapter));
factories.add(dateAdapterFactory);
if (sqlTypesSupported) {
factories.add(sqlTimestampAdapterFactory);
factories.add(sqlDateAdapterFactory);
}
}
}

View File

@ -339,6 +339,7 @@ public final class $Gson$Types {
}
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
return resolve(context, contextRawType, toResolve, new HashMap<TypeVariable<?>, Type>());
}

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
package com.google.gson;
package com.google.gson.internal.bind;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
@ -27,6 +26,10 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.PreJava9DateFormatProvider;
import com.google.gson.internal.bind.util.ISO8601Utils;
@ -35,17 +38,53 @@ import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
/**
* This type adapter supports three subclasses of date: Date, Timestamp, and
* java.sql.Date.
* This type adapter supports subclasses of date by defining a
* {@link DefaultDateTypeAdapter.DateType} and then using its {@code createAdapterFactory}
* methods.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
private static final String SIMPLE_NAME = "DefaultDateTypeAdapter";
private final Class<? extends Date> dateType;
public static abstract class DateType<T extends Date> {
public static final DateType<Date> DATE = new DateType<Date>(Date.class) {
@Override protected Date deserialize(Date date) {
return date;
}
};
private final Class<T> dateClass;
protected DateType(Class<T> dateClass) {
this.dateClass = dateClass;
}
protected abstract T deserialize(Date date);
private final TypeAdapterFactory createFactory(DefaultDateTypeAdapter<T> adapter) {
return TypeAdapters.newFactory(dateClass, adapter);
}
public final TypeAdapterFactory createAdapterFactory(String datePattern) {
return createFactory(new DefaultDateTypeAdapter<T>(this, datePattern));
}
public final TypeAdapterFactory createAdapterFactory(int style) {
return createFactory(new DefaultDateTypeAdapter<T>(this, style));
}
public final TypeAdapterFactory createAdapterFactory(int dateStyle, int timeStyle) {
return createFactory(new DefaultDateTypeAdapter<T>(this, dateStyle, timeStyle));
}
public final TypeAdapterFactory createDefaultsAdapterFactory() {
return createFactory(new DefaultDateTypeAdapter<T>(this, DateFormat.DEFAULT, DateFormat.DEFAULT));
}
}
private final DateType<T> dateType;
/**
* List of 1 or more different date formats used for de-serialization attempts.
@ -53,27 +92,16 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
*/
private final List<DateFormat> dateFormats = new ArrayList<DateFormat>();
DefaultDateTypeAdapter(Class<? extends Date> dateType) {
this.dateType = verifyDateType(dateType);
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US));
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
if (JavaVersion.isJava9OrLater()) {
dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
}
DefaultDateTypeAdapter(Class<? extends Date> dateType, String datePattern) {
this.dateType = verifyDateType(dateType);
private DefaultDateTypeAdapter(DateType<T> dateType, String datePattern) {
this.dateType = $Gson$Preconditions.checkNotNull(dateType);
dateFormats.add(new SimpleDateFormat(datePattern, Locale.US));
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(new SimpleDateFormat(datePattern));
}
}
DefaultDateTypeAdapter(Class<? extends Date> dateType, int style) {
this.dateType = verifyDateType(dateType);
private DefaultDateTypeAdapter(DateType<T> dateType, int style) {
this.dateType = $Gson$Preconditions.checkNotNull(dateType);
dateFormats.add(DateFormat.getDateInstance(style, Locale.US));
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateInstance(style));
@ -83,12 +111,8 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
}
}
public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
this(Date.class, dateStyle, timeStyle);
}
public DefaultDateTypeAdapter(Class<? extends Date> dateType, int dateStyle, int timeStyle) {
this.dateType = verifyDateType(dateType);
private DefaultDateTypeAdapter(DateType<T> dateType, int dateStyle, int timeStyle) {
this.dateType = $Gson$Preconditions.checkNotNull(dateType);
dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US));
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle));
@ -98,13 +122,6 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
}
}
private static Class<? extends Date> verifyDateType(Class<? extends Date> dateType) {
if ( dateType != Date.class && dateType != java.sql.Date.class && dateType != Timestamp.class ) {
throw new IllegalArgumentException("Date type must be one of " + Date.class + ", " + Timestamp.class + ", or " + java.sql.Date.class + " but was " + dateType);
}
return dateType;
}
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
// See issue 162
@Override
@ -120,22 +137,13 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
}
@Override
public Date read(JsonReader in) throws IOException {
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Date date = deserializeToDate(in.nextString());
if (dateType == Date.class) {
return date;
} else if (dateType == Timestamp.class) {
return new Timestamp(date.getTime());
} else if (dateType == java.sql.Date.class) {
return new java.sql.Date(date.getTime());
} else {
// This must never happen: dateType is guarded in the primary constructor
throw new AssertionError();
}
return dateType.deserialize(date);
}
private Date deserializeToDate(String s) {
@ -145,11 +153,12 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
return dateFormat.parse(s);
} catch (ParseException ignored) {}
}
try {
return ISO8601Utils.parse(s, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(s, e);
}
}
try {
return ISO8601Utils.parse(s, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(s, e);
}
}

View File

@ -26,12 +26,10 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
@ -409,7 +407,7 @@ public final class TypeAdapters {
out.value(value);
}
};
public static final TypeAdapter<BigDecimal> BIG_DECIMAL = new TypeAdapter<BigDecimal>() {
@Override public BigDecimal read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
@ -427,7 +425,7 @@ public final class TypeAdapters {
out.value(value);
}
};
public static final TypeAdapter<BigInteger> BIG_INTEGER = new TypeAdapter<BigInteger>() {
@Override public BigInteger read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
@ -572,27 +570,6 @@ public final class TypeAdapters {
}.nullSafe();
public static final TypeAdapterFactory CURRENCY_FACTORY = newFactory(Currency.class, CURRENCY);
public static final TypeAdapterFactory TIMESTAMP_FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (typeToken.getRawType() != Timestamp.class) {
return null;
}
final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter<T>) new TypeAdapter<Timestamp>() {
@Override public Timestamp read(JsonReader in) throws IOException {
Date date = dateTypeAdapter.read(in);
return date != null ? new Timestamp(date.getTime()) : null;
}
@Override public void write(JsonWriter out, Timestamp value) throws IOException {
dateTypeAdapter.write(out, value);
}
};
}
};
public static final TypeAdapter<Calendar> CALENDAR = new TypeAdapter<Calendar>() {
private static final String YEAR = "year";
private static final String MONTH = "month";

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson.internal.bind;
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@ -35,8 +35,8 @@ import java.text.SimpleDateFormat;
* this class state. DateFormat isn't thread safe either, so this class has
* to synchronize its read and write methods.
*/
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == java.sql.Date.class
@ -46,6 +46,9 @@ public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
private SqlDateTypeAdapter() {
}
@Override
public synchronized java.sql.Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson.internal.bind;
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@ -32,21 +32,24 @@ import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Adapter for Time. Although this class appears stateless, it is not.
* Adapter for java.sql.Time. Although this class appears stateless, it is not.
* DateFormat captures its time zone and locale when it is created, which gives
* this class state. DateFormat isn't thread safe either, so this class has
* to synchronize its read and write methods.
*/
public final class TimeTypeAdapter extends TypeAdapter<Time> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
final class SqlTimeTypeAdapter extends TypeAdapter<Time> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new TimeTypeAdapter() : null;
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new SqlTimeTypeAdapter() : null;
}
};
private final DateFormat format = new SimpleDateFormat("hh:mm:ss a");
private SqlTimeTypeAdapter() {
}
@Override public synchronized Time read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();

View File

@ -0,0 +1,43 @@
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
class SqlTimestampTypeAdapter extends TypeAdapter<Timestamp> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (typeToken.getRawType() == Timestamp.class) {
final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter<T>) new SqlTimestampTypeAdapter(dateTypeAdapter);
} else {
return null;
}
}
};
private final TypeAdapter<Date> dateTypeAdapter;
private SqlTimestampTypeAdapter(TypeAdapter<Date> dateTypeAdapter) {
this.dateTypeAdapter = dateTypeAdapter;
}
@Override
public Timestamp read(JsonReader in) throws IOException {
Date date = dateTypeAdapter.read(in);
return date != null ? new Timestamp(date.getTime()) : null;
}
@Override
public void write(JsonWriter out, Timestamp value) throws IOException {
dateTypeAdapter.write(out, value);
}
}

View File

@ -0,0 +1,71 @@
package com.google.gson.internal.sql;
import java.sql.Timestamp;
import java.util.Date;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.bind.DefaultDateTypeAdapter.DateType;
/**
* Encapsulates access to {@code java.sql} types, to allow Gson to
* work without the {@code java.sql} module being present.
* No {@link ClassNotFoundException}s will be thrown in case
* the {@code java.sql} module is not present.
*
* <p>If {@link #SUPPORTS_SQL_TYPES} is {@code true}, all other
* constants of this class will be non-{@code null}. However, if
* it is {@code false} all other constants will be {@code null} and
* there will be no support for {@code java.sql} types.
*/
public final class SqlTypesSupport {
/**
* {@code true} if {@code java.sql} types are supported,
* {@code false} otherwise
*/
public static final boolean SUPPORTS_SQL_TYPES;
public static final DateType<? extends Date> DATE_DATE_TYPE;
public static final DateType<? extends Date> TIMESTAMP_DATE_TYPE;
public static final TypeAdapterFactory DATE_FACTORY;
public static final TypeAdapterFactory TIME_FACTORY;
public static final TypeAdapterFactory TIMESTAMP_FACTORY;
static {
boolean sqlTypesSupport;
try {
Class.forName("java.sql.Date");
sqlTypesSupport = true;
} catch (ClassNotFoundException classNotFoundException) {
sqlTypesSupport = false;
}
SUPPORTS_SQL_TYPES = sqlTypesSupport;
if (SUPPORTS_SQL_TYPES) {
DATE_DATE_TYPE = new DateType<java.sql.Date>(java.sql.Date.class) {
@Override protected java.sql.Date deserialize(Date date) {
return new java.sql.Date(date.getTime());
}
};
TIMESTAMP_DATE_TYPE = new DateType<Timestamp>(Timestamp.class) {
@Override protected Timestamp deserialize(Date date) {
return new Timestamp(date.getTime());
}
};
DATE_FACTORY = SqlDateTypeAdapter.FACTORY;
TIME_FACTORY = SqlTimeTypeAdapter.FACTORY;
TIMESTAMP_FACTORY = SqlTimestampTypeAdapter.FACTORY;
} else {
DATE_DATE_TYPE = null;
TIMESTAMP_DATE_TYPE = null;
DATE_FACTORY = null;
TIME_FACTORY = null;
TIMESTAMP_FACTORY = null;
}
}
private SqlTypesSupport() {
}
}

View File

@ -8,5 +8,6 @@ module com.google.gson {
exports com.google.gson.reflect;
exports com.google.gson.stream;
requires transitive java.sql;
// Optional dependency on java.sql
requires static java.sql;
}

View File

@ -37,7 +37,6 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.common.MoreAsserts;
import com.google.gson.common.TestTypes.BagOfPrimitives;
import com.google.gson.reflect.TypeToken;

View File

@ -69,12 +69,14 @@ import junit.framework.TestCase;
public class DefaultTypeAdaptersTest extends TestCase {
private Gson gson;
private TimeZone oldTimeZone;
private Locale oldLocale;
@Override
protected void setUp() throws Exception {
super.setUp();
this.oldTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
this.oldLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
gson = new Gson();
}
@ -82,6 +84,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
@Override
protected void tearDown() throws Exception {
TimeZone.setDefault(oldTimeZone);
Locale.setDefault(oldLocale);
super.tearDown();
}
@ -146,7 +149,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
URI target = gson.fromJson(json, URI.class);
assertEquals(uriValue, target.toASCIIString());
}
public void testNullSerialization() throws Exception {
testNullSerializationAndDeserialization(Boolean.class);
testNullSerializationAndDeserialization(Byte.class);
@ -175,14 +178,15 @@ public class DefaultTypeAdaptersTest extends TestCase {
testNullSerializationAndDeserialization(Date.class);
testNullSerializationAndDeserialization(GregorianCalendar.class);
testNullSerializationAndDeserialization(Calendar.class);
testNullSerializationAndDeserialization(Time.class);
testNullSerializationAndDeserialization(Timestamp.class);
testNullSerializationAndDeserialization(java.sql.Date.class);
testNullSerializationAndDeserialization(Enum.class);
testNullSerializationAndDeserialization(Class.class);
}
private void testNullSerializationAndDeserialization(Class<?> c) {
testNullSerializationAndDeserialization(gson, c);
}
public static void testNullSerializationAndDeserialization(Gson gson, Class<?> c) {
assertEquals("null", gson.toJson(null, c));
assertEquals(null, gson.fromJson("null", c));
}
@ -269,7 +273,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
ClassWithBigInteger actual = gson.fromJson(json, ClassWithBigInteger.class);
assertEquals(expected.value, actual.value);
}
public void testOverrideBigIntegerTypeAdapter() throws Exception {
gson = new GsonBuilder()
.registerTypeAdapter(BigInteger.class, new NumberAsStringAdapter(BigInteger.class))
@ -347,60 +351,19 @@ public class DefaultTypeAdaptersTest extends TestCase {
// Date can not directly be compared with another instance since the deserialization loses the
// millisecond portion.
@SuppressWarnings("deprecation")
private void assertEqualsDate(Date date, int year, int month, int day) {
public static void assertEqualsDate(Date date, int year, int month, int day) {
assertEquals(year-1900, date.getYear());
assertEquals(month, date.getMonth());
assertEquals(day, date.getDate());
}
@SuppressWarnings("deprecation")
private void assertEqualsTime(Date date, int hours, int minutes, int seconds) {
public static void assertEqualsTime(Date date, int hours, int minutes, int seconds) {
assertEquals(hours, date.getHours());
assertEquals(minutes, date.getMinutes());
assertEquals(seconds, date.getSeconds());
}
public void testDefaultJavaSqlDateSerialization() {
java.sql.Date instant = new java.sql.Date(1259875082000L);
String json = gson.toJson(instant);
assertEquals("\"Dec 3, 2009\"", json);
}
public void testDefaultJavaSqlDateDeserialization() {
String json = "'Dec 3, 2009'";
java.sql.Date extracted = gson.fromJson(json, java.sql.Date.class);
assertEqualsDate(extracted, 2009, 11, 3);
}
public void testDefaultJavaSqlTimestampSerialization() {
Timestamp now = new java.sql.Timestamp(1259875082000L);
String json = gson.toJson(now);
if (JavaVersion.isJava9OrLater()) {
assertEquals("\"Dec 3, 2009, 1:18:02 PM\"", json);
} else {
assertEquals("\"Dec 3, 2009 1:18:02 PM\"", json);
}
}
public void testDefaultJavaSqlTimestampDeserialization() {
String json = "'Dec 3, 2009 1:18:02 PM'";
Timestamp extracted = gson.fromJson(json, Timestamp.class);
assertEqualsDate(extracted, 2009, 11, 3);
assertEqualsTime(extracted, 13, 18, 2);
}
public void testDefaultJavaSqlTimeSerialization() {
Time now = new Time(1259875082000L);
String json = gson.toJson(now);
assertEquals("\"01:18:02 PM\"", json);
}
public void testDefaultJavaSqlTimeDeserialization() {
String json = "'1:18:02 PM'";
Time extracted = gson.fromJson(json, Time.class);
assertEqualsTime(extracted, 13, 18, 2);
}
public void testDefaultDateSerializationUsingBuilder() throws Exception {
Gson gson = new GsonBuilder().create();
Date now = new Date(1315806903103L);
@ -524,42 +487,6 @@ public class DefaultTypeAdaptersTest extends TestCase {
}
}
// 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);
}
}
public void testJsonPrimitiveSerialization() {
assertEquals("5", gson.toJson(new JsonPrimitive(5), JsonElement.class));
assertEquals("true", gson.toJson(new JsonPrimitive(true), JsonElement.class));

View File

@ -172,6 +172,7 @@ public class TreeTypeAdaptersTest extends TestCase {
int numClasses;
}
@SafeVarargs
private static <T> List<T> createList(T ...items) {
return Arrays.asList(items);
}

View File

@ -280,6 +280,7 @@ public final class LinkedHashTreeMapTest extends TestCase {
}
}
@SafeVarargs
private <T> void assertIterationOrder(Iterable<T> actual, T... expected) {
ArrayList<T> actualList = new ArrayList<T>();
for (T t : actual) {

View File

@ -140,6 +140,7 @@ public final class LinkedTreeMapTest extends TestCase {
MoreAsserts.assertEqualsAndHashCode(map1, map2);
}
@SafeVarargs
private <T> void assertIterationOrder(Iterable<T> actual, T... expected) {
ArrayList<T> actualList = new ArrayList<T>();
for (T t : actual) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson;
package com.google.gson.internal.bind;
import java.io.IOException;
import java.text.DateFormat;
@ -23,7 +23,13 @@ import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.bind.DefaultDateTypeAdapter;
import com.google.gson.internal.bind.DefaultDateTypeAdapter.DateType;
import com.google.gson.reflect.TypeToken;
import junit.framework.TestCase;
@ -52,18 +58,18 @@ public class DefaultDateTypeAdapterTest extends TestCase {
String afterYearLongSep = JavaVersion.isJava9OrLater() ? " at " : " ";
String utcFull = JavaVersion.isJava9OrLater() ? "Coordinated Universal Time" : "UTC";
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertFormatted("1/1/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT));
assertFormatted("Jan 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.MEDIUM));
assertFormatted("January 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.LONG));
DateType.DATE.createDefaultsAdapterFactory());
assertFormatted("1/1/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertFormatted("Jan 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertFormatted("January 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertFormatted(String.format("1/1/70%s12:00 AM", afterYearSep),
new DefaultDateTypeAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertFormatted(String.format("January 1, 1970%s12:00:00 AM UTC", afterYearLongSep),
new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertFormatted(String.format("Thursday, January 1, 1970%s12:00:00 AM %s", afterYearLongSep, utcFull),
new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -78,21 +84,21 @@ public class DefaultDateTypeAdapterTest extends TestCase {
try {
String afterYearSep = JavaVersion.isJava9OrLater() ? " à " : " ";
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertParsed("01/01/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT));
assertParsed("1 janv. 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.MEDIUM));
assertParsed("1 janvier 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.LONG));
DateType.DATE.createDefaultsAdapterFactory());
assertParsed("01/01/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertParsed("1 janv. 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertParsed("1 janvier 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertParsed("01/01/70 00:00",
new DefaultDateTypeAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertParsed(String.format("1 janvier 1970%s00:00:00 UTC", afterYearSep),
new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertParsed(JavaVersion.isJava9OrLater() ? (JavaVersion.getMajorJavaVersion() <11 ?
"jeudi 1 janvier 1970 à 00:00:00 Coordinated Universal Time" :
"jeudi 1 janvier 1970 à 00:00:00 Temps universel coordonné") :
"jeudi 1 janvier 1970 00 h 00 UTC",
new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -105,18 +111,18 @@ public class DefaultDateTypeAdapterTest extends TestCase {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
assertParsed("Jan 1, 1970 0:00:00 AM", new DefaultDateTypeAdapter(Date.class));
assertParsed("1/1/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT));
assertParsed("Jan 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.MEDIUM));
assertParsed("January 1, 1970", new DefaultDateTypeAdapter(Date.class, DateFormat.LONG));
assertParsed("Jan 1, 1970 0:00:00 AM", DateType.DATE.createDefaultsAdapterFactory());
assertParsed("1/1/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertParsed("Jan 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertParsed("January 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertParsed("1/1/70 0:00 AM",
new DefaultDateTypeAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertParsed("Jan 1, 1970 0:00:00 AM",
new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertParsed("January 1, 1970 0:00:00 AM UTC",
new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertParsed("Thursday, January 1, 1970 0:00:00 AM UTC",
new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -131,8 +137,8 @@ public class DefaultDateTypeAdapterTest extends TestCase {
try {
String afterYearSep = JavaVersion.isJava9OrLater() ? ", " : " ";
assertFormatted(String.format("Dec 31, 1969%s4:00:00 PM", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertParsed("Dec 31, 1969 4:00:00 PM", new DefaultDateTypeAdapter(Date.class));
DateType.DATE.createDefaultsAdapterFactory());
assertParsed("Dec 31, 1969 4:00:00 PM", DateType.DATE.createDefaultsAdapterFactory());
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -140,17 +146,17 @@ public class DefaultDateTypeAdapterTest extends TestCase {
}
public void testDateDeserializationISO8601() throws Exception {
DefaultDateTypeAdapter adapter = new DefaultDateTypeAdapter(Date.class);
assertParsed("1970-01-01T00:00:00.000Z", adapter);
assertParsed("1970-01-01T00:00Z", adapter);
assertParsed("1970-01-01T00:00:00+00:00", adapter);
assertParsed("1970-01-01T01:00:00+01:00", adapter);
assertParsed("1970-01-01T01:00:00+01", adapter);
TypeAdapterFactory adapterFactory = DateType.DATE.createDefaultsAdapterFactory();
assertParsed("1970-01-01T00:00:00.000Z", adapterFactory);
assertParsed("1970-01-01T00:00Z", adapterFactory);
assertParsed("1970-01-01T00:00:00+00:00", adapterFactory);
assertParsed("1970-01-01T01:00:00+01:00", adapterFactory);
assertParsed("1970-01-01T01:00:00+01", adapterFactory);
}
public void testDateSerialization() throws Exception {
int dateStyle = DateFormat.LONG;
DefaultDateTypeAdapter dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, dateStyle);
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(dateStyle));
DateFormat formatter = DateFormat.getDateInstance(dateStyle, Locale.US);
Date currentDate = new Date();
@ -160,7 +166,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
public void testDatePattern() throws Exception {
String pattern = "yyyy-MM-dd";
DefaultDateTypeAdapter dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, pattern);
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(pattern));
DateFormat formatter = new SimpleDateFormat(pattern);
Date currentDate = new Date();
@ -168,33 +174,40 @@ public class DefaultDateTypeAdapterTest extends TestCase {
assertEquals(toLiteral(formatter.format(currentDate)), dateString);
}
@SuppressWarnings("unused")
public void testInvalidDatePattern() throws Exception {
try {
new DefaultDateTypeAdapter(Date.class, "I am a bad Date pattern....");
DateType.DATE.createAdapterFactory("I am a bad Date pattern....");
fail("Invalid date pattern should fail.");
} catch (IllegalArgumentException expected) { }
}
public void testNullValue() throws Exception {
DefaultDateTypeAdapter adapter = new DefaultDateTypeAdapter(Date.class);
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
assertNull(adapter.fromJson("null"));
assertEquals("null", adapter.toJson(null));
}
public void testUnexpectedToken() throws Exception {
try {
DefaultDateTypeAdapter adapter = new DefaultDateTypeAdapter(Date.class);
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
adapter.fromJson("{}");
fail("Unexpected token should fail.");
} catch (IllegalStateException expected) { }
}
private void assertFormatted(String formatted, DefaultDateTypeAdapter adapter) {
private static TypeAdapter<Date> dateAdapter(TypeAdapterFactory adapterFactory) {
TypeAdapter<Date> adapter = adapterFactory.create(new Gson(), TypeToken.get(Date.class));
assertNotNull(adapter);
return adapter;
}
private static void assertFormatted(String formatted, TypeAdapterFactory adapterFactory) {
TypeAdapter<Date> adapter = dateAdapter(adapterFactory);
assertEquals(toLiteral(formatted), adapter.toJson(new Date(0)));
}
private void assertParsed(String date, DefaultDateTypeAdapter adapter) throws IOException {
private static void assertParsed(String date, TypeAdapterFactory adapterFactory) throws IOException {
TypeAdapter<Date> adapter = dateAdapter(adapterFactory);
assertEquals(date, new Date(0), adapter.fromJson(toLiteral(date)));
assertEquals("ISO 8601", new Date(0), adapter.fromJson(toLiteral("1970-01-01T00:00:00Z")));
}

View File

@ -36,7 +36,7 @@ public class RecursiveTypesResolveTest extends TestCase {
@SuppressWarnings("unused")
private static class Foo1<A> {
public Foo2<? extends A> foo2;
public Foo2<? extends A> foo2;
}
@SuppressWarnings("unused")
private static class Foo2<B> {
@ -48,6 +48,7 @@ public class RecursiveTypesResolveTest extends TestCase {
*/
public void testRecursiveResolveSimple() {
@SuppressWarnings("rawtypes")
TypeAdapter<Foo1> adapter = new Gson().getAdapter(Foo1.class);
assertNotNull(adapter);
}
@ -62,6 +63,7 @@ public class RecursiveTypesResolveTest extends TestCase {
}
public void testIssue440WeakReference() throws Exception {
@SuppressWarnings("rawtypes")
TypeAdapter<WeakReference> adapter = new Gson().getAdapter(WeakReference.class);
assertNotNull(adapter);
}
@ -105,11 +107,13 @@ public class RecursiveTypesResolveTest extends TestCase {
}
public void testRecursiveTypeVariablesResolve1() throws Exception {
@SuppressWarnings("rawtypes")
TypeAdapter<TestType> adapter = new Gson().getAdapter(TestType.class);
assertNotNull(adapter);
}
public void testRecursiveTypeVariablesResolve12() throws Exception {
@SuppressWarnings("rawtypes")
TypeAdapter<TestType2> adapter = new Gson().getAdapter(TestType2.class);
assertNotNull(adapter);
}

View File

@ -0,0 +1,124 @@
package com.google.gson.internal.sql;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Locale;
import java.util.TimeZone;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.functional.DefaultTypeAdaptersTest;
import com.google.gson.internal.JavaVersion;
import junit.framework.TestCase;
public class SqlTypesGsonTest extends TestCase {
private Gson gson;
private TimeZone oldTimeZone;
private Locale oldLocale;
@Override
protected void setUp() throws Exception {
super.setUp();
this.oldTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
this.oldLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
gson = new Gson();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TimeZone.setDefault(oldTimeZone);
Locale.setDefault(oldLocale);
}
public void testNullSerializationAndDeserialization() {
testNullSerializationAndDeserialization(Date.class);
testNullSerializationAndDeserialization(Time.class);
testNullSerializationAndDeserialization(Timestamp.class);
}
private void testNullSerializationAndDeserialization(Class<?> c) {
DefaultTypeAdaptersTest.testNullSerializationAndDeserialization(gson, c);
}
public void testDefaultSqlDateSerialization() {
java.sql.Date instant = new java.sql.Date(1259875082000L);
String json = gson.toJson(instant);
assertEquals("\"Dec 3, 2009\"", json);
}
public void testDefaultSqlDateDeserialization() {
String json = "'Dec 3, 2009'";
java.sql.Date extracted = gson.fromJson(json, java.sql.Date.class);
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
}
// 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);
}
}
public void testDefaultSqlTimeSerialization() {
Time now = new Time(1259875082000L);
String json = gson.toJson(now);
assertEquals("\"01:18:02 PM\"", json);
}
public void testDefaultSqlTimeDeserialization() {
String json = "'1:18:02 PM'";
Time extracted = gson.fromJson(json, Time.class);
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
}
public void testDefaultSqlTimestampSerialization() {
Timestamp now = new java.sql.Timestamp(1259875082000L);
String json = gson.toJson(now);
if (JavaVersion.isJava9OrLater()) {
assertEquals("\"Dec 3, 2009, 1:18:02 PM\"", json);
} else {
assertEquals("\"Dec 3, 2009 1:18:02 PM\"", json);
}
}
public void testDefaultSqlTimestampDeserialization() {
String json = "'Dec 3, 2009 1:18:02 PM'";
Timestamp extracted = gson.fromJson(json, Timestamp.class);
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
}
// 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);
}
}
}

View File

@ -0,0 +1,16 @@
package com.google.gson.internal.sql;
import junit.framework.TestCase;
public class SqlTypesSupportTest extends TestCase {
public void testSupported() {
assertTrue(SqlTypesSupport.SUPPORTS_SQL_TYPES);
assertNotNull(SqlTypesSupport.DATE_DATE_TYPE);
assertNotNull(SqlTypesSupport.TIMESTAMP_DATE_TYPE);
assertNotNull(SqlTypesSupport.DATE_FACTORY);
assertNotNull(SqlTypesSupport.TIME_FACTORY);
assertNotNull(SqlTypesSupport.TIMESTAMP_FACTORY);
}
}