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.
|
// constants will appear as nulls.
|
||||||
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
|
private static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_SERIALIZERS =
|
||||||
createDefaultSerializers();
|
createDefaultSerializers();
|
||||||
|
static final ParameterizedTypeHandlerMap<JsonSerializer<?>> DEFAULT_HIERARCHY_SERIALIZERS =
|
||||||
|
createDefaultHierarchySerializers();
|
||||||
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
|
private static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_DESERIALIZERS =
|
||||||
createDefaultDeserializers();
|
createDefaultDeserializers();
|
||||||
|
static final ParameterizedTypeHandlerMap<JsonDeserializer<?>> DEFAULT_HIERARCHY_DESERIALIZERS =
|
||||||
|
createDefaultHierarchyDeserializers();
|
||||||
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
|
private static final ParameterizedTypeHandlerMap<InstanceCreator<?>> DEFAULT_INSTANCE_CREATORS =
|
||||||
createDefaultInstanceCreators();
|
createDefaultInstanceCreators();
|
||||||
|
|
||||||
@ -108,14 +112,10 @@ final class DefaultTypeAdapters {
|
|||||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
|
ParameterizedTypeHandlerMap<JsonSerializer<?>> map =
|
||||||
new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
|
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(URL.class, URL_TYPE_ADAPTER);
|
||||||
map.register(URI.class, URI_TYPE_ADAPTER);
|
map.register(URI.class, URI_TYPE_ADAPTER);
|
||||||
map.register(UUID.class, UUUID_TYPE_ADAPTER);
|
map.register(UUID.class, UUUID_TYPE_ADAPTER);
|
||||||
map.register(Locale.class, LOCALE_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(Date.class, DATE_TYPE_ADAPTER);
|
||||||
map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER);
|
map.register(java.sql.Date.class, JAVA_SQL_DATE_TYPE_ADAPTER);
|
||||||
map.register(Timestamp.class, DATE_TYPE_ADAPTER);
|
map.register(Timestamp.class, DATE_TYPE_ADAPTER);
|
||||||
@ -143,17 +143,24 @@ 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);
|
||||||
|
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() {
|
private static ParameterizedTypeHandlerMap<JsonDeserializer<?>> createDefaultDeserializers() {
|
||||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
|
ParameterizedTypeHandlerMap<JsonDeserializer<?>> map =
|
||||||
new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
|
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(URL.class, wrapDeserializer(URL_TYPE_ADAPTER));
|
||||||
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
|
map.register(URI.class, wrapDeserializer(URI_TYPE_ADAPTER));
|
||||||
map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER));
|
map.register(UUID.class, wrapDeserializer(UUUID_TYPE_ADAPTER));
|
||||||
map.register(Locale.class, wrapDeserializer(LOCALE_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(Date.class, wrapDeserializer(DATE_TYPE_ADAPTER));
|
||||||
map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER));
|
map.register(java.sql.Date.class, wrapDeserializer(JAVA_SQL_DATE_TYPE_ADAPTER));
|
||||||
map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER));
|
map.register(Timestamp.class, wrapDeserializer(TIMESTAMP_DESERIALIZER));
|
||||||
@ -187,6 +194,17 @@ 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));
|
||||||
|
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() {
|
private static ParameterizedTypeHandlerMap<InstanceCreator<?>> createDefaultInstanceCreators() {
|
||||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> map =
|
ParameterizedTypeHandlerMap<InstanceCreator<?>> map =
|
||||||
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
|
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
|
||||||
@ -211,6 +229,20 @@ final class DefaultTypeAdapters {
|
|||||||
return getDefaultSerializers(false, LongSerializationPolicy.DEFAULT);
|
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(
|
static ParameterizedTypeHandlerMap<JsonSerializer<?>> getDefaultSerializers(
|
||||||
boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) {
|
boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy) {
|
||||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
|
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers =
|
||||||
|
@ -152,8 +152,8 @@ 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,
|
||||||
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
||||||
false, DefaultTypeAdapters.getDefaultSerializers(),
|
false, DefaultTypeAdapters.getAllDefaultSerializers(),
|
||||||
DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
|
DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
||||||
|
@ -522,8 +522,12 @@ public final class GsonBuilder {
|
|||||||
ExclusionStrategy deserializationExclusionStrategy =
|
ExclusionStrategy deserializationExclusionStrategy =
|
||||||
new DisjunctionExclusionStrategy(deserializationStrategies);
|
new DisjunctionExclusionStrategy(deserializationStrategies);
|
||||||
|
|
||||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
|
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers =
|
||||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers = deserializers.copyOf();
|
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,
|
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
|
||||||
customDeserializers);
|
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) {
|
public synchronized void registerIfAbsent(Type typeOfT, T value) {
|
||||||
if (!modifiable) {
|
if (!modifiable) {
|
||||||
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
|
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
|
||||||
|
@ -16,6 +16,14 @@
|
|||||||
|
|
||||||
package com.google.gson.functional;
|
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.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
@ -28,14 +36,6 @@ import com.google.gson.JsonSerializer;
|
|||||||
import com.google.gson.common.MoreAsserts;
|
import com.google.gson.common.MoreAsserts;
|
||||||
import com.google.gson.reflect.TypeToken;
|
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.
|
* Functional tests for Java 5.0 enums.
|
||||||
*
|
*
|
||||||
@ -120,17 +120,6 @@ public class EnumTest extends TestCase {
|
|||||||
* Test for issue 226.
|
* Test for issue 226.
|
||||||
*/
|
*/
|
||||||
public void testEnumSubclass() {
|
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());
|
assertFalse(Roshambo.class == Roshambo.ROCK.getClass());
|
||||||
assertEquals("\"ROCK\"", gson.toJson(Roshambo.ROCK));
|
assertEquals("\"ROCK\"", gson.toJson(Roshambo.ROCK));
|
||||||
assertEquals("[\"ROCK\",\"PAPER\",\"SCISSORS\"]", gson.toJson(EnumSet.allOf(Roshambo.class)));
|
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()));
|
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 {
|
public enum Roshambo {
|
||||||
ROCK {
|
ROCK {
|
||||||
@Override Roshambo defeats() {
|
@Override Roshambo defeats() {
|
||||||
|
Loading…
Reference in New Issue
Block a user