Fix a regression I introduced with the changes to type hierarchy registration. If the registered type was a raw type, we need to also match the parameterizations of that type.
This commit is contained in:
parent
a069f4d883
commit
9a80d095d9
@ -70,11 +70,9 @@ public final class GsonBuilder {
|
||||
private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
|
||||
private final Map<Type, InstanceCreator<?>> instanceCreators
|
||||
= new HashMap<Type, InstanceCreator<?>>();
|
||||
private final List<TypeAdapter.Factory> factories
|
||||
= new ArrayList<TypeAdapter.Factory>();
|
||||
private final List<TypeAdapter.Factory> factories = new ArrayList<TypeAdapter.Factory>();
|
||||
/** tree-style hierarchy factories. These come after factories for backwards compatibility. */
|
||||
private final List<TypeAdapter.Factory> hierarchyFactories
|
||||
= new ArrayList<TypeAdapter.Factory>();
|
||||
private final List<TypeAdapter.Factory> hierarchyFactories = new ArrayList<TypeAdapter.Factory>();
|
||||
private boolean serializeNulls;
|
||||
private String datePattern;
|
||||
private int dateStyle = DateFormat.DEFAULT;
|
||||
@ -452,11 +450,11 @@ public final class GsonBuilder {
|
||||
"Cannot register type adapters for " + type);
|
||||
}
|
||||
if (typeAdapter instanceof InstanceCreator<?>) {
|
||||
registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter);
|
||||
instanceCreators.put(type, (InstanceCreator) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
|
||||
TypeToken<?> typeToken = TypeToken.get(type);
|
||||
factories.add(TreeTypeAdapter.newFactory(typeToken, typeAdapter));
|
||||
factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
|
||||
}
|
||||
if (typeAdapter instanceof TypeAdapter<?>) {
|
||||
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
|
||||
@ -475,37 +473,19 @@ public final class GsonBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to use a custom {@link InstanceCreator} for the specified type. If an instance
|
||||
* creator was previously registered for the specified class, it is overwritten. Since this method
|
||||
* takes a type instead of a Class object, it can be used to register a specific handler for a
|
||||
* generic type corresponding to a raw type.
|
||||
*
|
||||
*
|
||||
* @param typeOfT The Type definition for T
|
||||
* @param instanceCreator the instance creator for T
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
private <T> GsonBuilder registerInstanceCreator(Type typeOfT,
|
||||
InstanceCreator<? extends T> instanceCreator) {
|
||||
instanceCreators.put(typeOfT, instanceCreator);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
|
||||
* This method combines the registration of an {@link InstanceCreator}, {@link JsonSerializer},
|
||||
* and a {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter}
|
||||
* implements all the required interfaces for custom serialization with Gson.
|
||||
* If an instance creator, serializer or deserializer was previously registered for the specified
|
||||
* type hierarchy, it is overwritten. If an instance creator, serializer or deserializer is
|
||||
* registered for a specific type in the type hierarchy, it will be invoked instead of the one
|
||||
* registered for the type hierarchy.
|
||||
* This method combines the registration of a {@link JsonSerializer} and a {@link
|
||||
* JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements both of
|
||||
* the required interfaces for custom serialization with Gson. If a serializer or deserializer was
|
||||
* previously registered for the specified type hierarchy, it is overwritten. If a serializer or
|
||||
* deserializer is registered for a specific type in the type hierarchy, it will be invoked
|
||||
* instead of the one registered for the type hierarchy.
|
||||
*
|
||||
* @param baseType the class definition for the type adapter being registered for the base class
|
||||
* or interface
|
||||
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
|
||||
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
|
||||
* @param typeAdapter This object must implement at least one of {@link JsonSerializer} or {@link
|
||||
* JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.7
|
||||
*/
|
||||
|
@ -78,21 +78,40 @@ final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
||||
: (delegate = gson.getNextAdapter(skipPast, typeToken));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new factory that will match each type against {@code exactType}.
|
||||
*/
|
||||
public static Factory newFactory(TypeToken<?> exactType, Object typeAdapter) {
|
||||
return new SingleTypeFactory(typeAdapter, exactType, null);
|
||||
return new SingleTypeFactory(typeAdapter, exactType, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new factory that will match each type and its raw type against
|
||||
* {@code exactType}.
|
||||
*/
|
||||
public static Factory newFactoryWithMatchRawType(TypeToken<?> exactType, Object typeAdapter) {
|
||||
// only bother matching raw types if exact type is a raw type
|
||||
boolean matchRawType = exactType.getType() == exactType.getRawType();
|
||||
return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new factory that will match each type's raw type for assignability
|
||||
* to {@code hierarchyType}.
|
||||
*/
|
||||
public static Factory newTypeHierarchyFactory(Class<?> hierarchyType, Object typeAdapter) {
|
||||
return new SingleTypeFactory(typeAdapter, null, hierarchyType);
|
||||
return new SingleTypeFactory(typeAdapter, null, false, hierarchyType);
|
||||
}
|
||||
|
||||
private static class SingleTypeFactory implements TypeAdapter.Factory {
|
||||
private final TypeToken<?> exactType;
|
||||
private final boolean matchRawType;
|
||||
private final Class<?> hierarchyType;
|
||||
private final JsonSerializer<?> serializer;
|
||||
private final JsonDeserializer<?> deserializer;
|
||||
|
||||
private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, Class<?> hierarchyType) {
|
||||
private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
|
||||
Class<?> hierarchyType) {
|
||||
serializer = typeAdapter instanceof JsonSerializer
|
||||
? (JsonSerializer) typeAdapter
|
||||
: null;
|
||||
@ -101,13 +120,14 @@ final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
||||
: null;
|
||||
$Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
|
||||
this.exactType = exactType;
|
||||
this.matchRawType = matchRawType;
|
||||
this.hierarchyType = hierarchyType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // guarded by typeToken.equals() call
|
||||
public <T> TypeAdapter<T> create(Gson context, TypeToken<T> type) {
|
||||
boolean matches = exactType != null
|
||||
? exactType.equals(type)
|
||||
? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
|
||||
: hierarchyType.isAssignableFrom(type.getRawType());
|
||||
return matches
|
||||
? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
|
||||
|
Loading…
Reference in New Issue
Block a user