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

View File

@ -16,7 +16,6 @@
package com.google.gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.internal.Primitives;
import com.google.gson.internal.Streams;
@ -46,7 +45,6 @@ import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@ -104,7 +102,7 @@ public final class Gson {
@SuppressWarnings("rawtypes")
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
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 ExclusionStrategy deserializationExclusionStrategy;
private final ExclusionStrategy serializationExclusionStrategy;
private final ConstructorConstructor constructorConstructor;
/** Map containing Type or Class objects as keys */
@ -215,8 +211,6 @@ public final class Gson {
boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapter.Factory> typeAdapterFactories) {
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.serializers = serializers;
@ -225,27 +219,9 @@ public final class Gson {
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
TypeAdapter.Factory reflectiveTypeAdapterFactory
= new ReflectiveTypeAdapterFactory(constructorConstructor) {
@Override
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));
}
};
TypeAdapter.Factory reflectiveTypeAdapterFactory = new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, serializationExclusionStrategy,
deserializationExclusionStrategy);
ConstructorConstructor constructorConstructor = new ConstructorConstructor();
List<TypeAdapter.Factory> factories = new ArrayList<TypeAdapter.Factory>();

View File

@ -16,9 +16,13 @@
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.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.internal.$Gson$Types;
import com.google.gson.internal.ConstructorConstructor;
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.
*/
public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
public final class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
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.fieldNamingPolicy = fieldNamingPolicy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
}
protected boolean serializeField(Class<?> declaringClazz, Field f, Type declaredType) {
return !f.isSynthetic();
public boolean serializeField(Field f) {
return !serializationExclusionStrategy.shouldSkipClass(f.getType())
&& !serializationExclusionStrategy.shouldSkipField(new FieldAttributes(f));
}
protected boolean deserializeField(Class<?> declaringClazz, Field f, Type declaredType) {
return !f.isSynthetic();
private boolean deserializeField(Field f) {
return !deserializationExclusionStrategy.shouldSkipClass(f.getType())
&& !deserializationExclusionStrategy.shouldSkipField(new FieldAttributes(f));
}
protected String getFieldName(Class<?> declaringClazz, Field f, Type declaredType) {
return f.getName();
private String getFieldName(Field f) {
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) {
@ -93,8 +108,7 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
};
}
private Map<String, BoundField> getBoundFields(
Gson context, TypeToken<?> type, Class<?> raw) {
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) {
return result;
@ -105,13 +119,13 @@ public class ReflectiveTypeAdapterFactory implements TypeAdapter.Factory {
Field[] fields = raw.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field field : fields) {
boolean serialize = serializeField(raw, field, declaredType);
boolean deserialize = deserializeField(raw, field, declaredType);
boolean serialize = serializeField(field);
boolean deserialize = deserializeField(field);
if (!serialize && !deserialize) {
continue;
}
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);
BoundField previous = result.put(boundField.name, boundField);
if (previous != null) {

View File

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

View File

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

View File

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

View File

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

View File

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