Make dependency on java.sql optional
This commit is contained in:
parent
361292f1c1
commit
380c4ec12c
@ -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
|
||||
@ -604,23 +605,33 @@ public final class GsonBuilder {
|
||||
|
||||
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
|
||||
List<TypeAdapterFactory> factories) {
|
||||
DefaultDateTypeAdapter<Date> dateTypeAdapter;
|
||||
TypeAdapter<Timestamp> timestampTypeAdapter;
|
||||
TypeAdapter<java.sql.Date> javaSqlDateTypeAdapter;
|
||||
if (datePattern != null && !"".equals(datePattern.trim())) {
|
||||
dateTypeAdapter = DefaultDateTypeAdapter.DateType.DATE.createAdapter(datePattern);
|
||||
timestampTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_TIMESTAMP.createAdapter(datePattern);
|
||||
javaSqlDateTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_DATE.createAdapter(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 = DefaultDateTypeAdapter.DateType.DATE.createAdapter(dateStyle, timeStyle);
|
||||
timestampTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_TIMESTAMP.createAdapter(dateStyle, timeStyle);
|
||||
javaSqlDateTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_DATE.createAdapter(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,9 @@ 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.JavaVersion;
|
||||
import com.google.gson.internal.PreJava9DateFormatProvider;
|
||||
import com.google.gson.internal.bind.util.ISO8601Utils;
|
||||
@ -35,54 +37,49 @@ 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<T extends Date> extends TypeAdapter<T> {
|
||||
public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
|
||||
private static final String SIMPLE_NAME = "DefaultDateTypeAdapter";
|
||||
|
||||
static abstract class DateType<T extends Date> {
|
||||
private DateType() {
|
||||
}
|
||||
|
||||
public static final DateType<Date> DATE = new DateType<Date>() {
|
||||
@Override
|
||||
protected Date deserialize(Date date) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
public static final DateType<java.sql.Date> SQL_DATE = new DateType<java.sql.Date>() {
|
||||
@Override
|
||||
protected java.sql.Date deserialize(Date date) {
|
||||
return new java.sql.Date(date.getTime());
|
||||
}
|
||||
};
|
||||
public static final DateType<Timestamp> SQL_TIMESTAMP = new DateType<Timestamp>() {
|
||||
@Override
|
||||
protected Timestamp deserialize(Date date) {
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
};
|
||||
|
||||
private final Class<T> dateClass;
|
||||
|
||||
protected DateType(Class<T> dateClass) {
|
||||
this.dateClass = dateClass;
|
||||
}
|
||||
|
||||
protected abstract T deserialize(Date date);
|
||||
|
||||
public DefaultDateTypeAdapter<T> createAdapter(String datePattern) {
|
||||
return new DefaultDateTypeAdapter<T>(this, datePattern);
|
||||
private final TypeAdapterFactory createFactory(DefaultDateTypeAdapter<T> adapter) {
|
||||
return TypeAdapters.newFactory(dateClass, adapter);
|
||||
}
|
||||
|
||||
public DefaultDateTypeAdapter<T> createAdapter(int style) {
|
||||
return new DefaultDateTypeAdapter<T>(this, style);
|
||||
public final TypeAdapterFactory createAdapterFactory(String datePattern) {
|
||||
return createFactory(new DefaultDateTypeAdapter<T>(this, datePattern));
|
||||
}
|
||||
|
||||
public DefaultDateTypeAdapter<T> createAdapter(int dateStyle, int timeStyle) {
|
||||
return new DefaultDateTypeAdapter<T>(this, dateStyle, timeStyle);
|
||||
public final TypeAdapterFactory createAdapterFactory(int style) {
|
||||
return createFactory(new DefaultDateTypeAdapter<T>(this, style));
|
||||
}
|
||||
|
||||
public DefaultDateTypeAdapter<T> createDefaultsAdapter() {
|
||||
return new DefaultDateTypeAdapter<T>(this, DateFormat.DEFAULT, DateFormat.DEFAULT);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,11 +159,12 @@ final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,10 @@ import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
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;
|
||||
@ -406,7 +404,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) {
|
||||
@ -424,7 +422,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) {
|
||||
@ -569,27 +567,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;
|
||||
}
|
||||
|
@ -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,8 +23,13 @@ import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.google.gson.DefaultDateTypeAdapter.DateType;
|
||||
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;
|
||||
|
||||
@ -53,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),
|
||||
DateType.DATE.createDefaultsAdapter());
|
||||
assertFormatted("1/1/70", DateType.DATE.createAdapter(DateFormat.SHORT));
|
||||
assertFormatted("Jan 1, 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
|
||||
assertFormatted("January 1, 1970", DateType.DATE.createAdapter(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),
|
||||
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
|
||||
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
|
||||
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
assertFormatted(String.format("January 1, 1970%s12:00:00 AM UTC", afterYearLongSep),
|
||||
DateType.DATE.createAdapter(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),
|
||||
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTimeZone);
|
||||
Locale.setDefault(defaultLocale);
|
||||
@ -79,21 +84,21 @@ public class DefaultDateTypeAdapterTest extends TestCase {
|
||||
try {
|
||||
String afterYearSep = JavaVersion.isJava9OrLater() ? " à " : " ";
|
||||
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
|
||||
DateType.DATE.createDefaultsAdapter());
|
||||
assertParsed("01/01/70", DateType.DATE.createAdapter(DateFormat.SHORT));
|
||||
assertParsed("1 janv. 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
|
||||
assertParsed("1 janvier 1970", DateType.DATE.createAdapter(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",
|
||||
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
|
||||
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
|
||||
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
assertParsed(String.format("1 janvier 1970%s00:00:00 UTC", afterYearSep),
|
||||
DateType.DATE.createAdapter(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",
|
||||
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTimeZone);
|
||||
Locale.setDefault(defaultLocale);
|
||||
@ -106,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", DateType.DATE.createDefaultsAdapter());
|
||||
assertParsed("1/1/70", DateType.DATE.createAdapter(DateFormat.SHORT));
|
||||
assertParsed("Jan 1, 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
|
||||
assertParsed("January 1, 1970", DateType.DATE.createAdapter(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",
|
||||
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
|
||||
assertParsed("Jan 1, 1970 0:00:00 AM",
|
||||
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
|
||||
assertParsed("January 1, 1970 0:00:00 AM UTC",
|
||||
DateType.DATE.createAdapter(DateFormat.LONG, DateFormat.LONG));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
|
||||
assertParsed("Thursday, January 1, 1970 0:00:00 AM UTC",
|
||||
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
|
||||
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTimeZone);
|
||||
Locale.setDefault(defaultLocale);
|
||||
@ -132,8 +137,8 @@ public class DefaultDateTypeAdapterTest extends TestCase {
|
||||
try {
|
||||
String afterYearSep = JavaVersion.isJava9OrLater() ? ", " : " ";
|
||||
assertFormatted(String.format("Dec 31, 1969%s4:00:00 PM", afterYearSep),
|
||||
DateType.DATE.createDefaultsAdapter());
|
||||
assertParsed("Dec 31, 1969 4:00:00 PM", DateType.DATE.createDefaultsAdapter());
|
||||
DateType.DATE.createDefaultsAdapterFactory());
|
||||
assertParsed("Dec 31, 1969 4:00:00 PM", DateType.DATE.createDefaultsAdapterFactory());
|
||||
} finally {
|
||||
TimeZone.setDefault(defaultTimeZone);
|
||||
Locale.setDefault(defaultLocale);
|
||||
@ -141,17 +146,17 @@ public class DefaultDateTypeAdapterTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testDateDeserializationISO8601() throws Exception {
|
||||
DefaultDateTypeAdapter<Date> adapter = DateType.DATE.createDefaultsAdapter();
|
||||
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<Date> dateTypeAdapter = DateType.DATE.createAdapter(dateStyle);
|
||||
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(dateStyle));
|
||||
DateFormat formatter = DateFormat.getDateInstance(dateStyle, Locale.US);
|
||||
Date currentDate = new Date();
|
||||
|
||||
@ -161,7 +166,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
|
||||
|
||||
public void testDatePattern() throws Exception {
|
||||
String pattern = "yyyy-MM-dd";
|
||||
DefaultDateTypeAdapter<Date> dateTypeAdapter = DateType.DATE.createAdapter(pattern);
|
||||
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(pattern));
|
||||
DateFormat formatter = new SimpleDateFormat(pattern);
|
||||
Date currentDate = new Date();
|
||||
|
||||
@ -171,30 +176,38 @@ public class DefaultDateTypeAdapterTest extends TestCase {
|
||||
|
||||
public void testInvalidDatePattern() throws Exception {
|
||||
try {
|
||||
DateType.DATE.createAdapter("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<Date> adapter = DateType.DATE.createDefaultsAdapter();
|
||||
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
|
||||
assertNull(adapter.fromJson("null"));
|
||||
assertEquals("null", adapter.toJson(null));
|
||||
}
|
||||
|
||||
public void testUnexpectedToken() throws Exception {
|
||||
try {
|
||||
DefaultDateTypeAdapter<Date> adapter = DateType.DATE.createDefaultsAdapter();
|
||||
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
|
||||
adapter.fromJson("{}");
|
||||
fail("Unexpected token should fail.");
|
||||
} catch (IllegalStateException expected) { }
|
||||
}
|
||||
|
||||
private void assertFormatted(String formatted, DefaultDateTypeAdapter<Date> 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<Date> 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")));
|
||||
}
|
@ -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