Registering default type hierarchy adapters first and allow users to override them.
This allows the default EnumTypeAdapter to be overridden for a specific hierachy adapter for Enum with anonymized sub-classes.
This commit is contained in:
parent
fd0f526fb0
commit
2b9f81e8b5
@ -99,8 +99,12 @@ final class DefaultTypeAdapters {
|
||||
// constants will appear as nulls.
|
||||
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
|
||||
createDefaultSerializers();
|
||||
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_HIERARCHY_SERIALIZERS =
|
||||
createDefaultHierarchySerializers();
|
||||
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
|
||||
createDefaultDeserializers();
|
||||
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_HIERARCHY_DESERIALIZERS =
|
||||
createDefaultHierarchyDeserializers();
|
||||
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
|
||||
createDefaultInstanceCreators();
|
||||
|
||||
@ -108,14 +112,10 @@ final class DefaultTypeAdapters {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
||||
|
||||
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(InetAddress.class, INET_ADDRESS_ADAPTER);
|
||||
map.register(URL.class, URL_TYPE_ADAPTER);
|
||||
map.register(URI.class, URI_TYPE_ADAPTER);
|
||||
map.register(UUID.class, UUUID_TYPE_ADAPTER);
|
||||
map.register(Locale.class, LOCALE_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
|
||||
map.register(Date.class, DATE_TYPE_ADAPTER);
|
||||
map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER);
|
||||
map.register(Timestamp.class, DATE_TYPE_ADAPTER);
|
||||
@ -143,17 +143,24 @@ final class DefaultTypeAdapters {
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<JsonSerializer<?>> createDefaultHierarchySerializers() {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
||||
map.registerForTypeHierarchy(Enum.class, ENUM_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(InetAddress.class, INET_ADDRESS_ADAPTER);
|
||||
map.registerForTypeHierarchy(Collection.class, COLLECTION_TYPE_ADAPTER);
|
||||
map.registerForTypeHierarchy(Map.class, MAP_TYPE_ADAPTER);
|
||||
map.makeUnmodifiable();
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
|
||||
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(InetAddress.class, wrapDeserializer(INET_ADDRESS_ADAPTER));
|
||||
map.register(URL.class, wrapDeserializer(URL_TYPE_ADAPTER));
|
||||
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
|
||||
map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER));
|
||||
map.register(Locale.class, wrapDeserializer(LOCALE_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER));
|
||||
map.register(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER));
|
||||
map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER));
|
||||
map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER));
|
||||
@ -187,6 +194,17 @@ final class DefaultTypeAdapters {
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultHierarchyDeserializers() {
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
|
||||
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
|
||||
map.registerForTypeHierarchy(Enum.class, wrapDeserializer(ENUM_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(InetAddress.class, wrapDeserializer(INET_ADDRESS_ADAPTER));
|
||||
map.registerForTypeHierarchy(Collection.class, wrapDeserializer(COLLECTION_TYPE_ADAPTER));
|
||||
map.registerForTypeHierarchy(Map.class, wrapDeserializer(MAP_TYPE_ADAPTER));
|
||||
map.makeUnmodifiable();
|
||||
return map;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
|
||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> map =
|
||||
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
|
||||
@ -211,6 +229,20 @@ final class DefaultTypeAdapters {
|
||||
return getDefaultSerializers(false, LongSerializationPolicy.DEFAULT);
|
||||
}
|
||||
|
||||
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getAllDefaultSerializers() {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> defaultSerializers =
|
||||
getDefaultSerializers(false, LongSerializationPolicy.DEFAULT);
|
||||
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<JsonSerializer<?>> getDefaultSerializers(
|
||||
boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) {
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
|
||||
|
@ -152,8 +152,8 @@ public final class Gson {
|
||||
public Gson() {
|
||||
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
|
||||
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
||||
false, DefaultTypeAdapters.getDefaultSerializers(),
|
||||
DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
|
||||
false, DefaultTypeAdapters.getAllDefaultSerializers(),
|
||||
DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
|
||||
}
|
||||
|
||||
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
||||
|
@ -522,8 +522,12 @@ public final class GsonBuilder {
|
||||
ExclusionStrategy deserializationExclusionStrategy =
|
||||
new DisjunctionExclusionStrategy(deserializationStrategies);
|
||||
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers =
|
||||
DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf();
|
||||
customSerializers.register(serializers.copyOf());
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers =
|
||||
DefaultTypeAdapters.DEFAULT_HIERARCHY_DESERIALIZERS.copyOf();
|
||||
customDeserializers.register(deserializers.copyOf());
|
||||
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
|
||||
customDeserializers);
|
||||
|
||||
|
@ -105,6 +105,21 @@ final class ParameterizedTypeHandlerMap<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void register(ParameterizedTypeHandlerMap<T> other) {
|
||||
if (!modifiable) {
|
||||
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
|
||||
}
|
||||
for (Map.Entry<Type, T> entry : other.map.entrySet()) {
|
||||
register(entry.getKey(), entry.getValue());
|
||||
}
|
||||
// Quite important to traverse the typeHierarchyList from stack bottom first since
|
||||
// we want to register the handlers in the same order to preserve priority order
|
||||
for (int i = other.typeHierarchyList.size()-1; i >= 0; --i) {
|
||||
Pair<Class<?>, T> entry = other.typeHierarchyList.get(i);
|
||||
registerForTypeHierarchy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void registerIfAbsent(Type typeOfT, T value) {
|
||||
if (!modifiable) {
|
||||
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
|
||||
|
@ -16,6 +16,14 @@
|
||||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
@ -28,14 +36,6 @@ import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.common.MoreAsserts;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Functional tests for Java 5.0 enums.
|
||||
*
|
||||
@ -120,17 +120,6 @@ public class EnumTest extends TestCase {
|
||||
* Test for issue 226.
|
||||
*/
|
||||
public void testEnumSubclass() {
|
||||
assertRoshambo();
|
||||
}
|
||||
|
||||
public void disabled_testEnumSubclassWithRegisteredTypeAdapter() {
|
||||
gson = new GsonBuilder()
|
||||
// .registerTypeHierarchyAdapter(Roshambo.class, new MyEnumTypeAdapter())
|
||||
.create();
|
||||
assertRoshambo();
|
||||
}
|
||||
|
||||
private void assertRoshambo() {
|
||||
assertFalse(Roshambo.class == Roshambo.ROCK.getClass());
|
||||
assertEquals("\"ROCK\"", gson.toJson(Roshambo.ROCK));
|
||||
assertEquals("[\"ROCK\",\"PAPER\",\"SCISSORS\"]", gson.toJson(EnumSet.allOf(Roshambo.class)));
|
||||
@ -139,6 +128,18 @@ public class EnumTest extends TestCase {
|
||||
gson.fromJson("[\"ROCK\",\"PAPER\",\"SCISSORS\"]", new TypeToken<Set<Roshambo>>() {}.getType()));
|
||||
}
|
||||
|
||||
public void testEnumSubclassWithRegisteredTypeAdapter() {
|
||||
gson = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Roshambo.class, new MyEnumTypeAdapter())
|
||||
.create();
|
||||
assertFalse(Roshambo.class == Roshambo.ROCK.getClass());
|
||||
assertEquals("\"123ROCK\"", gson.toJson(Roshambo.ROCK));
|
||||
assertEquals("[\"123ROCK\",\"123PAPER\",\"123SCISSORS\"]", gson.toJson(EnumSet.allOf(Roshambo.class)));
|
||||
assertEquals(Roshambo.ROCK, gson.fromJson("\"123ROCK\"", Roshambo.class));
|
||||
assertEquals(EnumSet.allOf(Roshambo.class),
|
||||
gson.fromJson("[\"123ROCK\",\"123PAPER\",\"123SCISSORS\"]", new TypeToken<Set<Roshambo>>() {}.getType()));
|
||||
}
|
||||
|
||||
public enum Roshambo {
|
||||
ROCK {
|
||||
@Override Roshambo defeats() {
|
||||
|
Loading…
Reference in New Issue
Block a user