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.testBigIntegerInASingleElementArrayDeserialization
com.google.gson.functional.StringTest.testStringValueAsSingleElementArrayDeserialization
com.google.gson.functional.EnumTest.testTopLevelEnumInASingleElementArrayDeserialization
GSON 1.x permitted primitive types to be overridden
GSON 2.x doesn't.

View File

@ -47,9 +47,6 @@ final class DefaultTypeAdapters {
private static final DefaultTimestampDeserializer TIMESTAMP_DESERIALIZER =
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 NumberTypeAdapter NUMBER_TYPE_ADAPTER = new NumberTypeAdapter();
@ -59,15 +56,11 @@ final class DefaultTypeAdapters {
// The constants DEFAULT_SERIALIZERS, DEFAULT_DESERIALIZERS, and DEFAULT_INSTANCE_CREATORS
// must be defined after the constants for the type adapters. Otherwise, the type adapter
// constants will appear as nulls.
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
createDefaultSerializers();
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_HIERARCHY_SERIALIZERS =
createDefaultHierarchySerializers();
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
createDefaultDeserializers();
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_HIERARCHY_DESERIALIZERS =
createDefaultHierarchyDeserializers();
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
createDefaultInstanceCreators();
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultSerializers() {
@ -89,14 +82,6 @@ final class DefaultTypeAdapters {
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() {
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
@ -115,14 +100,6 @@ final class DefaultTypeAdapters {
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() {
ParameterizedTypeHandlerMap<InstanceCreator<?>> map
= new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
@ -135,32 +112,6 @@ final class DefaultTypeAdapters {
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
* 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
implements JsonSerializer<Number>, JsonDeserializer<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {

View File

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

View File

@ -669,21 +669,17 @@ public final class GsonBuilder {
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
}
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf();
customSerializers.register(serializers.copyOf());
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_DESERIALIZERS.copyOf();
customDeserializers.register(deserializers.copyOf());
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers);
customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers());
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers());
customSerializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_SERIALIZERS);
customDeserializers.registerIfAbsent(DefaultTypeAdapters.DEFAULT_DESERIALIZERS);
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
instanceCreators.copyOf();
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS);
customSerializers.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 <T> TypeAdapter.Factory newFactory(
final TypeToken<T> type, final TypeAdapter<T> typeAdapter) {
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
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() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -411,8 +439,8 @@ public final class TypeAdapters {
};
}
public static <T> TypeAdapter.Factory newFactory(
final Class<T> type, final TypeAdapter<T> typeAdapter) {
public static <TT> TypeAdapter.Factory newFactory(
final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -421,8 +449,8 @@ public final class TypeAdapters {
};
}
public static <T> TypeAdapter.Factory newFactory(
final Class<T> unboxed, final Class<T> boxed, final TypeAdapter<? super T> typeAdapter) {
public static <TT> TypeAdapter.Factory newFactory(
final Class<TT> unboxed, final Class<TT> boxed, final TypeAdapter<? super TT> typeAdapter) {
return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
@ -432,9 +460,10 @@ public final class TypeAdapters {
};
}
public static <T> TypeAdapter.Factory newTypeHierarchyFactory(
final Class<T> clazz, final TypeAdapter<T> typeAdapter) {
public static <TT> TypeAdapter.Factory newTypeHierarchyFactory(
final Class<TT> clazz, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapter.Factory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
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));
ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
Gson gson = new Gson(exclusionStrategy, exclusionStrategy, Gson.DEFAULT_NAMING_POLICY,
DefaultTypeAdapters.getDefaultInstanceCreators(),
false, DefaultTypeAdapters.getDefaultSerializers(),
DefaultTypeAdapters.getDefaultDeserializers(), false, Gson.DEFAULT_JSON_NON_EXECUTABLE,
DefaultTypeAdapters.DEFAULT_INSTANCE_CREATORS,
false, DefaultTypeAdapters.DEFAULT_SERIALIZERS,
DefaultTypeAdapters.DEFAULT_DESERIALIZERS, false, Gson.DEFAULT_JSON_NON_EXECUTABLE,
true, false, false, LongSerializationPolicy.DEFAULT);
assertEquals("{}", gson.toJson(new ClassWithNoFields() {
// empty anonymous class

View File

@ -62,12 +62,6 @@ public class EnumTest extends TestCase {
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() {
Type type = new TypeToken<Collection<MyEnum>>() {}.getType();
Collection<MyEnum> target = new ArrayList<MyEnum>();