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:
Jesse Wilson 2011-11-23 13:38:25 +00:00
parent a069f4d883
commit 9a80d095d9
2 changed files with 36 additions and 36 deletions

View File

@ -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
*/

View File

@ -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,