Smash together ReflectiveTypeAdapterFactory and its subclass. The separation was useful earlier when we were contemplating keeping Gson and MiniGson separate.

This commit is contained in:
Jesse Wilson 2011-11-21 05:42:30 +00:00
parent f39ac8d946
commit e23973afec
8 changed files with 51 additions and 69 deletions

View File

@ -58,8 +58,8 @@ public final class FieldAttributes {
* *
* @param f the field to pull attributes from * @param f the field to pull attributes from
*/ */
FieldAttributes(Class<?> declaringClazz, Field f) { public FieldAttributes(Field f) {
this.declaringClazz = $Gson$Preconditions.checkNotNull(declaringClazz); this.declaringClazz = f.getDeclaringClass();
this.name = f.getName(); this.name = f.getName();
this.declaredType = f.getType(); this.declaredType = f.getType();
this.isSynthetic = f.isSynthetic(); this.isSynthetic = f.isSynthetic();
@ -200,14 +200,6 @@ public final class FieldAttributes {
return isSynthetic; return isSynthetic;
} }
/**
* @deprecated remove this when {@link FieldNamingStrategy} is deleted.
*/
@Deprecated
Field getFieldObject() {
return field;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <T extends Annotation> T getAnnotationFromArray( private static <T extends Annotation> T getAnnotationFromArray(
Collection<Annotation> annotations, Class<T> annotation) { Collection<Annotation> annotations, Class<T> annotation) {

View File

@ -16,7 +16,6 @@
package com.google.gson; package com.google.gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.internal.ConstructorConstructor; import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.internal.Primitives; import com.google.gson.internal.Primitives;
import com.google.gson.internal.Streams; import com.google.gson.internal.Streams;
@ -46,7 +45,6 @@ import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -104,7 +102,7 @@ public final class Gson {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
static final TypeMap EMPTY_MAP = new TypeMap().makeUnmodifiable(); static final TypeMap EMPTY_MAP = new TypeMap().makeUnmodifiable();
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
// Default instances of plug-ins // Default instances of plug-ins
static final AnonymousAndLocalClassExclusionStrategy DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY = static final AnonymousAndLocalClassExclusionStrategy DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY =
@ -133,8 +131,6 @@ public final class Gson {
}; };
private final List<TypeAdapter.Factory> factories; private final List<TypeAdapter.Factory> factories;
private final ExclusionStrategy deserializationExclusionStrategy;
private final ExclusionStrategy serializationExclusionStrategy;
private final ConstructorConstructor constructorConstructor; private final ConstructorConstructor constructorConstructor;
/** Map containing Type or Class objects as keys */ /** Map containing Type or Class objects as keys */
@ -215,8 +211,6 @@ public final class Gson {
boolean prettyPrinting, boolean serializeSpecialFloatingPointValues, boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy, LongSerializationPolicy longSerializationPolicy,
List<TypeAdapter.Factory> typeAdapterFactories) { List<TypeAdapter.Factory> typeAdapterFactories) {
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.constructorConstructor = new ConstructorConstructor(instanceCreators); this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls; this.serializeNulls = serializeNulls;
this.serializers = serializers; this.serializers = serializers;
@ -225,27 +219,9 @@ public final class Gson {
this.htmlSafe = htmlSafe; this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting; this.prettyPrinting = prettyPrinting;
TypeAdapter.Factory reflectiveTypeAdapterFactory TypeAdapter.Factory reflectiveTypeAdapterFactory = new ReflectiveTypeAdapterFactory(
= new ReflectiveTypeAdapterFactory(constructorConstructor) { constructorConstructor, fieldNamingPolicy, serializationExclusionStrategy,
@Override deserializationExclusionStrategy);
public String getFieldName(Class<?> declaringClazz, Field f, Type declaredType) {
SerializedName serializedName = f.getAnnotation(SerializedName.class);
return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
}
@Override
public boolean serializeField(Class<?> declaringClazz, Field f, Type declaredType) {
ExclusionStrategy strategy = Gson.this.serializationExclusionStrategy;
return !strategy.shouldSkipClass(f.getType())
&& !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f));
}
@Override
public boolean deserializeField(Class<?> declaringClazz, Field f, Type declaredType) {
ExclusionStrategy strategy = Gson.this.deserializationExclusionStrategy;
return !strategy.shouldSkipClass(f.getType())
&& !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f));
}
};
ConstructorConstructor constructorConstructor = new ConstructorConstructor(); ConstructorConstructor constructorConstructor = new ConstructorConstructor();
List<TypeAdapter.Factory> factories = new ArrayList<TypeAdapter.Factory>(); List<TypeAdapter.Factory> factories = new ArrayList<TypeAdapter.Factory>();

View File

@ -16,9 +16,13 @@
package com.google.gson.internal.bind; package com.google.gson.internal.bind;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.internal.$Gson$Types; import com.google.gson.internal.$Gson$Types;
import com.google.gson.internal.ConstructorConstructor; import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.internal.ObjectConstructor; import com.google.gson.internal.ObjectConstructor;
@ -37,23 +41,34 @@ import java.util.Map;
/** /**
* Type adapter that reflects over the fields and methods of a class. * Type adapter that reflects over the fields and methods of a class.
*/ */
public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory { public final class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
private final ConstructorConstructor constructorConstructor; private final ConstructorConstructor constructorConstructor;
private final FieldNamingStrategy fieldNamingPolicy;
private final ExclusionStrategy serializationExclusionStrategy;
private final ExclusionStrategy deserializationExclusionStrategy;
public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor) { public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor,
FieldNamingStrategy fieldNamingPolicy, ExclusionStrategy serializationExclusionStrategy,
ExclusionStrategy deserializationExclusionStrategy) {
this.constructorConstructor = constructorConstructor; this.constructorConstructor = constructorConstructor;
this.fieldNamingPolicy = fieldNamingPolicy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
} }
protected boolean serializeField(Class<?> declaringClazz, Field f, Type declaredType) { public boolean serializeField(Field f) {
return !f.isSynthetic(); return !serializationExclusionStrategy.shouldSkipClass(f.getType())
&& !serializationExclusionStrategy.shouldSkipField(new FieldAttributes(f));
} }
protected boolean deserializeField(Class<?> declaringClazz, Field f, Type declaredType) { private boolean deserializeField(Field f) {
return !f.isSynthetic(); return !deserializationExclusionStrategy.shouldSkipClass(f.getType())
&& !deserializationExclusionStrategy.shouldSkipField(new FieldAttributes(f));
} }
protected String getFieldName(Class<?> declaringClazz, Field f, Type declaredType) { private String getFieldName(Field f) {
return f.getName(); SerializedName serializedName = f.getAnnotation(SerializedName.class);
return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
} }
public <T> TypeAdapter<T> create(Gson context, final TypeToken<T> type) { public <T> TypeAdapter<T> create(Gson context, final TypeToken<T> type) {
@ -93,8 +108,7 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
}; };
} }
private Map<String, BoundField> getBoundFields( private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>(); Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) { if (raw.isInterface()) {
return result; return result;
@ -105,13 +119,13 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
Field[] fields = raw.getDeclaredFields(); Field[] fields = raw.getDeclaredFields();
AccessibleObject.setAccessible(fields, true); AccessibleObject.setAccessible(fields, true);
for (Field field : fields) { for (Field field : fields) {
boolean serialize = serializeField(raw, field, declaredType); boolean serialize = serializeField(field);
boolean deserialize = deserializeField(raw, field, declaredType); boolean deserialize = deserializeField(field);
if (!serialize && !deserialize) { if (!serialize && !deserialize) {
continue; continue;
} }
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
BoundField boundField = createBoundField(context, field, getFieldName(raw, field, declaredType), BoundField boundField = createBoundField(context, field, getFieldName(field),
TypeToken.get(fieldType), serialize, deserialize); TypeToken.get(fieldType), serialize, deserialize);
BoundField previous = result.put(boundField.name, boundField); BoundField previous = result.put(boundField.name, boundField);
if (previous != null) { if (previous != null) {

View File

@ -28,14 +28,14 @@ import java.util.List;
*/ */
public class DisjunctionExclusionStrategyTest extends TestCase { public class DisjunctionExclusionStrategyTest extends TestCase {
private static final ExclusionStrategy FALSE_STRATEGY = private static final ExclusionStrategy FALSE_STRATEGY =
new MockExclusionStrategy(false, false); new MockExclusionStrategy(false, false);
private static final ExclusionStrategy TRUE_STRATEGY = private static final ExclusionStrategy TRUE_STRATEGY =
new MockExclusionStrategy(true, true); new MockExclusionStrategy(true, true);
private static final Class<?> CLAZZ = String.class; private static final Class<?> CLAZZ = String.class;
private static final FieldAttributes FIELD = private static final FieldAttributes FIELD =
new FieldAttributes(CLAZZ, CLAZZ.getFields()[0]); new FieldAttributes(CLAZZ.getFields()[0]);
public void testBadInstantiation() throws Exception { public void testBadInstantiation() throws Exception {
try { try {

View File

@ -66,18 +66,18 @@ public class ExposeAnnotationExclusionStrategyTest extends TestCase {
assertFalse(deserializationStrategy.shouldSkipField(f)); assertFalse(deserializationStrategy.shouldSkipField(f));
assertFalse(serializationStrategy.shouldSkipField(f)); assertFalse(serializationStrategy.shouldSkipField(f));
} }
public void testDifferentSerializeAndDeserializeField() throws Exception { public void testDifferentSerializeAndDeserializeField() throws Exception {
FieldAttributes f = createFieldAttributes("explicitlyDifferentModeField"); FieldAttributes f = createFieldAttributes("explicitlyDifferentModeField");
assertTrue(deserializationStrategy.shouldSkipField(f)); assertTrue(deserializationStrategy.shouldSkipField(f));
assertFalse(serializationStrategy.shouldSkipField(f)); assertFalse(serializationStrategy.shouldSkipField(f));
} }
private static FieldAttributes createFieldAttributes(String fieldName) throws Exception { private static FieldAttributes createFieldAttributes(String fieldName) throws Exception {
Field f = MockObject.class.getField(fieldName); Field f = MockObject.class.getField(fieldName);
return new FieldAttributes(MockObject.class, f); return new FieldAttributes(f);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static class MockObject { private static class MockObject {
@Expose @Expose
@ -88,7 +88,7 @@ public class ExposeAnnotationExclusionStrategyTest extends TestCase {
@Expose(serialize=false, deserialize=false) @Expose(serialize=false, deserialize=false)
public final int explicitlyHiddenField = 0; public final int explicitlyHiddenField = 0;
@Expose(serialize=true, deserialize=false) @Expose(serialize=true, deserialize=false)
public final int explicitlyDifferentModeField = 0; public final int explicitlyDifferentModeField = 0;

View File

@ -36,12 +36,12 @@ public class FieldAttributesTest extends TestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
fieldAttributes = new FieldAttributes(Foo.class, Foo.class.getField("bar")); fieldAttributes = new FieldAttributes(Foo.class.getField("bar"));
} }
public void testNullField() throws Exception { public void testNullField() throws Exception {
try { try {
new FieldAttributes(Foo.class, null); new FieldAttributes(null);
fail("Field parameter can not be null"); fail("Field parameter can not be null");
} catch (NullPointerException expected) { } } catch (NullPointerException expected) { }
} }

View File

@ -46,7 +46,7 @@ public class InnerClassExclusionStrategyTest extends TestCase {
public void testExcludeInnerClassField() throws Exception { public void testExcludeInnerClassField() throws Exception {
Field f = getClass().getField("innerClass"); Field f = getClass().getField("innerClass");
assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f))); assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
} }
public void testIncludeStaticNestedClassObject() throws Exception { public void testIncludeStaticNestedClassObject() throws Exception {
@ -56,7 +56,7 @@ public class InnerClassExclusionStrategyTest extends TestCase {
public void testIncludeStaticNestedClassField() throws Exception { public void testIncludeStaticNestedClassField() throws Exception {
Field f = getClass().getField("staticNestedClass"); Field f = getClass().getField("staticNestedClass");
assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f))); assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
} }
class InnerClass { class InnerClass {

View File

@ -43,7 +43,7 @@ public class VersionExclusionStrategyTest extends TestCase {
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION);
assertFalse(strategy.shouldSkipClass(clazz)); assertFalse(strategy.shouldSkipClass(clazz));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(f);
assertFalse(strategy.shouldSkipField(fieldAttributes)); assertFalse(strategy.shouldSkipField(fieldAttributes));
} }
@ -52,8 +52,8 @@ public class VersionExclusionStrategyTest extends TestCase {
Field f = clazz.getField("someField"); Field f = clazz.getField("someField");
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION + 1); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION + 1);
assertFalse(strategy.shouldSkipClass(clazz)); assertFalse(strategy.shouldSkipClass(clazz));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(f);
assertFalse(strategy.shouldSkipField(fieldAttributes)); assertFalse(strategy.shouldSkipField(fieldAttributes));
} }
@ -62,8 +62,8 @@ public class VersionExclusionStrategyTest extends TestCase {
Field f = clazz.getField("someField"); Field f = clazz.getField("someField");
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION - 1); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION - 1);
assertTrue(strategy.shouldSkipClass(clazz)); assertTrue(strategy.shouldSkipClass(clazz));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(f);
assertTrue(strategy.shouldSkipField(fieldAttributes)); assertTrue(strategy.shouldSkipField(fieldAttributes));
} }