Merge pull request #1707 from Marcono1234/optional-sql
Make dependency on java.sql optional
This commit is contained in:
commit
1023f0fe34
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
|
|
|
@ -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) {
|
|
@ -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();
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -172,6 +172,7 @@ public class TreeTypeAdaptersTest extends TestCase {
|
|||
int numClasses;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static <T> List<T> createList(T ...items) {
|
||||
return Arrays.asList(items);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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")));
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user