Added support for runtime type determination while serializing collections and its subclasses.
This currently doesn't work since Gson register a hierarchy type adapter for Collections that takes precedence over this.
This commit is contained in:
parent
e04d3fa882
commit
64dc53ffc4
@ -18,7 +18,6 @@ package com.google.gson.internal.bind;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -39,9 +38,6 @@ public final class CollectionTypeAdapter<E> extends TypeAdapter<Collection<E>> {
|
||||
public static final Factory FACTORY = new Factory() {
|
||||
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
|
||||
Type type = typeToken.getType();
|
||||
if (!(type instanceof ParameterizedType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<? super T> rawType = typeToken.getRawType();
|
||||
if (!Collection.class.isAssignableFrom(rawType)) {
|
||||
@ -69,16 +65,20 @@ public final class CollectionTypeAdapter<E> extends TypeAdapter<Collection<E>> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // create() doesn't define a type parameter
|
||||
TypeAdapter<T> result = new CollectionTypeAdapter(elementTypeAdapter, constructor);
|
||||
TypeAdapter<T> result = new CollectionTypeAdapter(context, elementType, elementTypeAdapter, constructor);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
private final MiniGson context;
|
||||
private final Type elementType;
|
||||
private final TypeAdapter<E> elementTypeAdapter;
|
||||
private final Constructor<? extends Collection<E>> constructor;
|
||||
|
||||
public CollectionTypeAdapter(TypeAdapter<E> elementTypeAdapter,
|
||||
public CollectionTypeAdapter(MiniGson context, Type elementType, TypeAdapter<E> elementTypeAdapter,
|
||||
Constructor<? extends Collection<E>> constructor) {
|
||||
this.context = context;
|
||||
this.elementType = elementType;
|
||||
this.elementTypeAdapter = elementTypeAdapter;
|
||||
this.constructor = constructor;
|
||||
}
|
||||
@ -107,7 +107,10 @@ public final class CollectionTypeAdapter<E> extends TypeAdapter<Collection<E>> {
|
||||
|
||||
writer.beginArray();
|
||||
for (E element : collection) {
|
||||
elementTypeAdapter.write(writer, element);
|
||||
Type runtimeType = Reflection.getRuntimeTypeIfMoreSpecific(elementType, collection, element);
|
||||
TypeAdapter t = runtimeType != elementType ?
|
||||
context.getAdapter(TypeToken.get(runtimeType)) : elementTypeAdapter;
|
||||
t.write(writer, element);
|
||||
}
|
||||
writer.endArray();
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package com.google.gson.common;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
@ -26,8 +29,6 @@ import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Types used for testing JSON serialization and deserialization
|
||||
*
|
||||
@ -66,6 +67,14 @@ public class TestTypes {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ClassWithBaseCollectionField {
|
||||
public static final String FIELD_KEY = "base";
|
||||
public final Collection<Base> base;
|
||||
public ClassWithBaseCollectionField(Collection<Base> base) {
|
||||
this.base = base;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BaseSerializer implements JsonSerializer<Base> {
|
||||
public static final String NAME = BaseSerializer.class.getSimpleName();
|
||||
public JsonElement serialize(Base src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
|
@ -15,19 +15,7 @@
|
||||
*/
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.common.TestTypes.BagOfPrimitives;
|
||||
import com.google.gson.common.TestTypes.Base;
|
||||
import com.google.gson.common.TestTypes.ClassWithBaseArrayField;
|
||||
import com.google.gson.common.TestTypes.ClassWithBaseField;
|
||||
import com.google.gson.common.TestTypes.Nested;
|
||||
import com.google.gson.common.TestTypes.Sub;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -36,6 +24,20 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.common.TestTypes.BagOfPrimitives;
|
||||
import com.google.gson.common.TestTypes.Base;
|
||||
import com.google.gson.common.TestTypes.ClassWithBaseArrayField;
|
||||
import com.google.gson.common.TestTypes.ClassWithBaseCollectionField;
|
||||
import com.google.gson.common.TestTypes.ClassWithBaseField;
|
||||
import com.google.gson.common.TestTypes.Nested;
|
||||
import com.google.gson.common.TestTypes.Sub;
|
||||
|
||||
/**
|
||||
* Functional tests for Json serialization and deserialization of classes with
|
||||
* inheritance hierarchies.
|
||||
@ -84,6 +86,18 @@ public class InheritanceTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClassWithBaseCollectionFieldSerialization() {
|
||||
Collection<Base> baseClasses = new ArrayList<Base>();
|
||||
baseClasses.add(new Sub());
|
||||
baseClasses.add(new Sub());
|
||||
ClassWithBaseCollectionField sub = new ClassWithBaseCollectionField(baseClasses);
|
||||
JsonObject json = gson.toJsonTree(sub).getAsJsonObject();
|
||||
JsonArray bases = json.get(ClassWithBaseArrayField.FIELD_KEY).getAsJsonArray();
|
||||
for (JsonElement element : bases) {
|
||||
assertEquals(Sub.SUB_NAME, element.getAsJsonObject().get(Sub.SUB_FIELD_KEY).getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public void testBaseSerializedAsSub() {
|
||||
Base base = new Sub();
|
||||
JsonObject json = gson.toJsonTree(base).getAsJsonObject();
|
||||
|
Loading…
Reference in New Issue
Block a user