Converted EnumTypeAdapter to new style.

Got rid of default Hierarchy Serializer/Deserializers from DefaultTypeAdapters.
Got rid of methods for gettting default serializers/deserializers/instance creators. Instead we reuse the static final instances.
Fixed warnings in TypeAdapters where a parameterized type T was hiding the parameterized T in methods.
Removed support to unwrap single element array of enums into enum values. Also removed the test that verifies this behavior.
This commit is contained in:
Inderjeet Singh 2011-09-16 05:40:05 +00:00
parent 915c5d4d6f
commit c71e61cf48
7 changed files with 53 additions and 100 deletions

View File

@ -11,6 +11,7 @@ com.google.gson.functional.PrimitiveTest.testPrimitiveDoubleAutoboxedInASingleEl
com.google.gson.functional.PrimitiveTest.testBigDecimalInASingleElementArrayDeserialization com.google.gson.functional.PrimitiveTest.testBigDecimalInASingleElementArrayDeserialization
com.google.gson.functional.PrimitiveTest.testBigIntegerInASingleElementArrayDeserialization com.google.gson.functional.PrimitiveTest.testBigIntegerInASingleElementArrayDeserialization
com.google.gson.functional.StringTest.testStringValueAsSingleElementArrayDeserialization com.google.gson.functional.StringTest.testStringValueAsSingleElementArrayDeserialization
com.google.gson.functional.EnumTest.testTopLevelEnumInASingleElementArrayDeserialization
GSON 1.x permitted primitive types to be overridden GSON 1.x permitted primitive types to be overridden
GSON 2.x doesn't. GSON 2.x doesn't.

View File

@ -47,9 +47,6 @@ final class DefaultTypeAdapters {
private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER = private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER =
new DefaultTimestampDeserializer(); new DefaultTimestampDeserializer();
@SuppressWarnings("unchecked")
private static final EnumTypeAdapter ENUM_TYPE_ADAPTER = new EnumTypeAdapter();
private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter(); private static final CharacterTypeAdapter CHARACTER_TYPE_ADAPTER = new CharacterTypeAdapter();
private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter(); private static final NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
@ -59,15 +56,11 @@ final class DefaultTypeAdapters {
// The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS // The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS
// must be defined after the constants for the type adapters. Otherwise, the type adapter // must be defined after the constants for the type adapters. Otherwise, the type adapter
// constants will appear as nulls. // constants will appear as nulls.
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS = static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
createDefaultSerializers(); createDefaultSerializers();
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_HIERARCHY_SERIALIZERS = static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
createDefaultHierarchySerializers();
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
createDefaultDeserializers(); createDefaultDeserializers();
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_HIERARCHY_DESERIALIZERS = static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
createDefaultHierarchyDeserializers();
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
createDefaultInstanceCreators(); createDefaultInstanceCreators();
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() { private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() {
@ -89,14 +82,6 @@ final class DefaultTypeAdapters {
return map; return map;
} }
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultHierarchySerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER, true);
map.makeUnmodifiable();
return map;
}
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() { private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map = ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>(); new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
@ -115,14 +100,6 @@ final class DefaultTypeAdapters {
return map; return map;
} }
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultHierarchyDeserializers() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER), true);
map.makeUnmodifiable();
return map;
}
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() { private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
ParameterizedTypeHandlerMap<InstanceCreator<?>> map ParameterizedTypeHandlerMap<InstanceCreator<?>> map
= new ParameterizedTypeHandlerMap<InstanceCreator<?>>(); = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
@ -135,32 +112,6 @@ final class DefaultTypeAdapters {
return new JsonDeserializerExceptionWrapper(deserializer); return new JsonDeserializerExceptionWrapper(deserializer);
} }
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers() {
return DEFAULT_SERIALIZERS.copyOf();
}
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getAllDefaultSerializers() {
ParameterizedTypeHandlerMap<JsonSerializer<?>> defaultSerializers =
DEFAULT_SERIALIZERS.copyOf();
defaultSerializers.register(DEFAULT_HIERARCHY_SERIALIZERS);
return defaultSerializers;
}
static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getAllDefaultDeserializers() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> defaultDeserializers =
getDefaultDeserializers().copyOf();
defaultDeserializers.register(DEFAULT_HIERARCHY_DESERIALIZERS);
return defaultDeserializers;
}
static ParameterizedTypeHandlerMap<JsonDeserializer<?>> getDefaultDeserializers() {
return DEFAULT_DESERIALIZERS;
}
static ParameterizedTypeHandlerMap<InstanceCreator<?>> getDefaultInstanceCreators() {
return DEFAULT_INSTANCE_CREATORS;
}
/** /**
* This type adapter supports three subclasses of date: Date, Timestamp, and * This type adapter supports three subclasses of date: Date, Timestamp, and
* java.sql.Date. * java.sql.Date.
@ -354,25 +305,6 @@ final class DefaultTypeAdapters {
} }
} }
@SuppressWarnings("unchecked")
private static final class EnumTypeAdapter<T extends Enum<T>>
implements JsonSerializer<T>, JsonDeserializer<T> {
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.name());
}
@SuppressWarnings("cast")
public T deserialize(JsonElement json, Type classOfT, JsonDeserializationContext context)
throws JsonParseException {
return (T) Enum.valueOf((Class<T>) classOfT, json.getAsString());
}
@Override
public String toString() {
return EnumTypeAdapter.class.getSimpleName();
}
}
private static final class NumberTypeAdapter private static final class NumberTypeAdapter
implements JsonSerializer<Number>, JsonDeserializer<Number> { implements JsonSerializer<Number>, JsonDeserializer<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) { public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {

View File

@ -168,9 +168,9 @@ public final class Gson {
*/ */
public Gson() { public Gson() {
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY, this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
DefaultTypeAdapters.getDefaultInstanceCreators(), DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS,
false, DefaultTypeAdapters.getAllDefaultSerializers(), false, DefaultTypeAdapters.DEFAULT_SERIALIZERS,
DefaultTypeAdapters.getAllDefaultDeserializers(), false, DEFAULT_JSON_NON_EXECUTABLE, true, DefaultTypeAdapters.DEFAULT_DESERIALIZERS, false, DEFAULT_JSON_NON_EXECUTABLE, true,
false, false, LongSerializationPolicy.DEFAULT); false, false, LongSerializationPolicy.DEFAULT);
} }
@ -254,6 +254,7 @@ public final class Gson {
)) ))
.factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)) .factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization))
.factory(ArrayTypeAdapter.FACTORY) .factory(ArrayTypeAdapter.FACTORY)
.factory(TypeAdapters.ENUM_FACTORY)
.factory(reflectiveTypeAdapterFactory); .factory(reflectiveTypeAdapterFactory);
this.miniGson = builder.build(); this.miniGson = builder.build();

View File

@ -669,21 +669,17 @@ public final class GsonBuilder {
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy); serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
} }
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf(); ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
customSerializers.register(serializers.copyOf());
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_DESERIALIZERS.copyOf();
customDeserializers.register(deserializers.copyOf());
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers, addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers); customDeserializers);
customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers()); customSerializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_SERIALIZERS);
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers()); customDeserializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_DESERIALIZERS);
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators = ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
instanceCreators.copyOf(); instanceCreators.copyOf();
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators()); customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS);
customSerializers.makeUnmodifiable(); customSerializers.makeUnmodifiable();
customDeserializers.makeUnmodifiable(); customDeserializers.makeUnmodifiable();

View File

@ -401,8 +401,36 @@ public final class TypeAdapters {
public static final TypeAdapter.Factory LOCALE_FACTORY = newFactory(Locale.class, LOCALE); public static final TypeAdapter.Factory LOCALE_FACTORY = newFactory(Locale.class, LOCALE);
public static <T> TypeAdapter.Factory newFactory( private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
final TypeToken<T> type, final TypeAdapter<T> typeAdapter) { private final Class<T> classOfT;
public EnumTypeAdapter(Class<T> classOfT) {
this.classOfT = classOfT;
}
public T read(JsonReader reader) throws IOException {
return (T) Enum.valueOf((Class<T>) classOfT, reader.nextString());
}
public void write(JsonWriter writer, T src) throws IOException {
writer.value(src.name());
}
};
public static final TypeAdapter.Factory ENUM_FACTORY = newEnumTypeHierarchyFactory(Enum.class);
public static <TT> TypeAdapter.Factory newEnumTypeHierarchyFactory(final Class<TT> clazz) {
return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
Class<? super T> rawType = typeToken.getRawType();
return clazz.isAssignableFrom(rawType)
? (TypeAdapter<T>) new EnumTypeAdapter(rawType) : null;
}
};
}
public static <TT> TypeAdapter.Factory newFactory(
final TypeToken<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapter.Factory() { return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) { public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -411,8 +439,8 @@ public final class TypeAdapters {
}; };
} }
public static <T> TypeAdapter.Factory newFactory( public static <TT> TypeAdapter.Factory newFactory(
final Class<T> type, final TypeAdapter<T> typeAdapter) { final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapter.Factory() { return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) { public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -421,8 +449,8 @@ public final class TypeAdapters {
}; };
} }
public static <T> TypeAdapter.Factory newFactory( public static <TT> TypeAdapter.Factory newFactory(
final Class<T> unboxed, final Class<T> boxed, final TypeAdapter<? super T> typeAdapter) { final Class<TT> unboxed, final Class<TT> boxed, final TypeAdapter<? super TT> typeAdapter) {
return new TypeAdapter.Factory() { return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) { public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -432,9 +460,10 @@ public final class TypeAdapters {
}; };
} }
public static <T> TypeAdapter.Factory newTypeHierarchyFactory( public static <TT> TypeAdapter.Factory newTypeHierarchyFactory(
final Class<T> clazz, final TypeAdapter<T> typeAdapter) { final Class<TT> clazz, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapter.Factory() { return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) { public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
return clazz.isAssignableFrom(typeToken.getRawType()) ? (TypeAdapter<T>) typeAdapter : null; return clazz.isAssignableFrom(typeToken.getRawType()) ? (TypeAdapter<T>) typeAdapter : null;
} }

View File

@ -37,9 +37,9 @@ public class FunctionWithInternalDependenciesTest extends TestCase {
strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC)); strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC));
ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies); ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
Gson gson = new Gson(exclusionStrategy, exclusionStrategy, Gson.DEFAULT_NAMING_POLICY, Gson gson = new Gson(exclusionStrategy, exclusionStrategy, Gson.DEFAULT_NAMING_POLICY,
DefaultTypeAdapters.getDefaultInstanceCreators(), DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS,
false, DefaultTypeAdapters.getDefaultSerializers(), false, DefaultTypeAdapters.DEFAULT_SERIALIZERS,
DefaultTypeAdapters.getDefaultDeserializers(), false, Gson.DEFAULT_JSON_NON_EXECUTABLE, DefaultTypeAdapters.DEFAULT_DESERIALIZERS, false, Gson.DEFAULT_JSON_NON_EXECUTABLE,
true, false, false, LongSerializationPolicy.DEFAULT); true, false, false, LongSerializationPolicy.DEFAULT);
assertEquals("{}", gson.toJson(new ClassWithNoFields() { assertEquals("{}", gson.toJson(new ClassWithNoFields() {
// empty anonymous class // empty anonymous class

View File

@ -62,12 +62,6 @@ public class EnumTest extends TestCase {
assertEquals(MyEnum.VALUE1, result); assertEquals(MyEnum.VALUE1, result);
} }
public void testTopLevelEnumInASingleElementArrayDeserialization() {
String json = "[" + MyEnum.VALUE1.getExpectedJson() + "]";
MyEnum target = gson.fromJson(json, MyEnum.class);
assertEquals(json, "[" + target.getExpectedJson() + "]");
}
public void testCollectionOfEnumsSerialization() { public void testCollectionOfEnumsSerialization() {
Type type = new TypeToken<Collection<MyEnum>>() {}.getType(); Type type = new TypeToken<Collection<MyEnum>>() {}.getType();
Collection<MyEnum> target = new ArrayList<MyEnum>(); Collection<MyEnum> target = new ArrayList<MyEnum>();