Use the same behavior in all situations when an InstanceCreator returns a subclass.

Previously we would set the field if the created instance is being assigned to a field of another object. We wouldn't set it when the created instance is a collection element or the top-level object.
This commit is contained in:
Jesse Wilson 2011-09-29 16:38:24 +00:00
parent 4d0775ce8e
commit 8b21c7770b
3 changed files with 11 additions and 22 deletions

View File

@ -45,4 +45,11 @@ GSON 2.x lets the runtime throw a StackOverflowError
com.google.gson.functional.CircularReferenceTest.testCircularSerialization
com.google.gson.functional.CircularReferenceTest.testSelfReferenceSerialization
com.google.gson.functional.CircularReferenceTest.testSelfReferenceArrayFieldSerialization
com.google.gson.functional.CircularReferenceTest.testSelfReferenceCustomHandlerSerialization
com.google.gson.functional.CircularReferenceTest.testSelfReferenceCustomHandlerSerialization
GSON 1.x sometimes sets subclass fields when an InstanceCreator returns a subclass.
This occurs only when the value is a field of another object: not when its
the top level object or a collection element.
GSON 2.x sets fields of the requested type only
com.google.gson.functional.InstanceCreatorTest.testInstanceCreatorReturnsSubTypeForField

View File

@ -25,7 +25,6 @@ import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
@ -63,9 +62,7 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
}
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(type);
return new Adapter<T>(context, constructor, type,
getBoundFields(context, type, raw));
return new Adapter<T>(constructor, getBoundFields(context, type, raw));
}
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
@ -142,16 +139,11 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
}
public final class Adapter<T> extends TypeAdapter<T> {
private final MiniGson context;
private final ObjectConstructor<T> constructor;
private final TypeToken<T> type;
private final Map<String, BoundField> boundFields;
private Adapter(MiniGson context, ObjectConstructor<T> constructor,
TypeToken<T> type, Map<String, BoundField> boundFields) {
this.context = context;
private Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.type = type;
this.boundFields = boundFields;
}
@ -194,16 +186,6 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
return;
}
// TODO: GSON includes subclass fields during serialization
// if (false) {
// Class<?> runtimeType = value.getClass();
// if (runtimeType != type.getRawType()) {
// TypeAdapter<?> adapter = context.getAdapter(runtimeType);
// ((TypeAdapter) adapter).write(writer, value);
// return;
// }
// }
writer.beginObject();
try {
for (BoundField boundField : boundFields.values()) {

View File

@ -77,6 +77,6 @@ public class InstanceCreatorTest extends TestCase {
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
assertTrue(target.base instanceof Sub);
assertEquals("SubRevised", ((Sub)target.base).subName);
assertEquals(Sub.SUB_NAME, ((Sub)target.base).subName);
}
}