Deprecate the FieldNamingStrategy interface and replace it with FieldNamingStrategy2. This is the first step to help make it easy to cache field annotations across all instances of a class, etc.

This commit is contained in:
Joel Leitch 2010-01-09 22:43:27 +00:00
parent 7079799890
commit e3af076ff2
25 changed files with 258 additions and 87 deletions

View File

@ -18,6 +18,7 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* Converts the field name that uses camel-case define word separation into separate words that
@ -56,7 +57,8 @@ final class CamelCaseSeparatorNamingPolicy extends RecursiveFieldNamingPolicy {
}
@Override
protected String translateName(String target, Type fieldType, Annotation[] annnotations) {
protected String translateName(String target, Type fieldType,
Collection<Annotation> annnotations) {
StringBuilder translation = new StringBuilder();
for (int i = 0; i < target.length(); i++) {
char character = target.charAt(i);

View File

@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
import java.lang.reflect.Field;
package com.google.gson;
/**
* Exception class to indicate a circular reference error.
@ -33,7 +32,7 @@ final class CircularReferenceException extends RuntimeException {
this.offendingNode = offendingNode;
}
public IllegalStateException createDetailedException(Field offendingField) {
public IllegalStateException createDetailedException(FieldAttributes offendingField) {
StringBuilder msg = new StringBuilder(getMessage());
if (offendingField != null) {
msg.append("\n ").append("Offending field: ").append(offendingField.getName() + "\n");

View File

@ -18,6 +18,7 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* Performs numerous field naming translations wrapped up as one object.
@ -36,7 +37,7 @@ abstract class CompositionFieldNamingPolicy extends RecursiveFieldNamingPolicy {
}
@Override
protected String translateName(String target, Type fieldType, Annotation[] annotations) {
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
for (RecursiveFieldNamingPolicy policy : fieldPolicies) {
target = policy.translateName(target, fieldType, annotations);
}

View File

@ -19,6 +19,9 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* A data object that stores attributes of a field.
@ -35,11 +38,11 @@ public final class FieldAttributes {
private final Class<?> declaredType;
private final boolean isSynthetic;
private final int modifiers;
private final String name;
// Fields used for lazy initialization
private String name;
private Type genericType;
private Annotation[] annotations;
private Collection<Annotation> annotations;
/**
* Constructs a Field Attributes object from the {@code f}.
@ -49,6 +52,7 @@ public final class FieldAttributes {
FieldAttributes(final Field f) {
Preconditions.checkNotNull(f);
field = f;
name = field.getName();
declaredType = f.getType();
isSynthetic = f.isSynthetic();
modifiers = field.getModifiers();
@ -58,9 +62,6 @@ public final class FieldAttributes {
* @return the name of the field
*/
public String getName() {
if (name == null) {
name = field.getName();
}
return name;
}
@ -115,10 +116,21 @@ public final class FieldAttributes {
* @return the annotation instance if it is bound to the field; otherwise {@code null}
*/
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
return getAnnotationFromArray(getAnnotations(), annotation);
}
/**
* Return the annotations that are present on this field.
*
* @return an array of all the annotations set on the field
* @since 1.4
*/
public Collection<Annotation> getAnnotations() {
if (annotations == null) {
annotations = field.getAnnotations();
annotations = Collections.unmodifiableCollection(
Arrays.asList(field.getAnnotations()));
}
return getAnnotationFromArray(annotations, annotation);
return annotations;
}
/**
@ -135,6 +147,28 @@ public final class FieldAttributes {
return (modifiers & modifier) != 0;
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
void set(Object instance, Object value) throws IllegalAccessException {
field.set(instance, value);
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
Object get(Object instance) throws IllegalAccessException {
return field.get(instance);
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
@ -143,10 +177,18 @@ public final class FieldAttributes {
boolean isSynthetic() {
return isSynthetic;
}
/**
* @deprecated remove this when {@link FieldNamingStrategy} is deleted.
*/
@Deprecated
Field getFieldObject() {
return field;
}
@SuppressWarnings("unchecked")
private static <T extends Annotation> T getAnnotationFromArray(
Annotation[] annotations, Class<T> annotation) {
Collection<Annotation> annotations, Class<T> annotation) {
for (Annotation a : annotations) {
if (a.annotationType() == annotation) {
return (T) a;

View File

@ -72,13 +72,13 @@ public enum FieldNamingPolicy {
*/
LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
private final FieldNamingStrategy namingPolicy;
private final FieldNamingStrategy2 namingPolicy;
private FieldNamingPolicy(FieldNamingStrategy namingPolicy) {
private FieldNamingPolicy(FieldNamingStrategy2 namingPolicy) {
this.namingPolicy = namingPolicy;
}
FieldNamingStrategy getFieldNamingPolicy() {
FieldNamingStrategy2 getFieldNamingPolicy() {
return namingPolicy;
}
}

View File

@ -26,7 +26,9 @@ import java.lang.reflect.Field;
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
* @deprecated use {@link FieldNamingStrategy2} instead
*/
@Deprecated
public interface FieldNamingStrategy {
/**

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
/**
* The new mechanism for providing custom field naming in Gson. This allows the client code
* to translate field names into a particular convention that is not supported as a normal
* Java field declaration rules. For example, Java does not support "-" characters in a
* field name.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.4
*/
public interface FieldNamingStrategy2 {
/**
* Translates the field name into its JSON field name representation.
*
* @param f the field that is being translated
* @return the translated field name.
* @since 1.3
*/
public String translateName(FieldAttributes f);
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
/**
* Adapts the old "deprecated" {@link FieldNamingStrategy} to the new {@link FieldNamingStrategy2}
* type.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
class FieldNamingStrategy2Adapter implements FieldNamingStrategy2 {
private final FieldNamingStrategy adaptee;
public FieldNamingStrategy2Adapter(FieldNamingStrategy adaptee) {
Preconditions.checkNotNull(adaptee);
this.adaptee = adaptee;
}
public String translateName(FieldAttributes f) {
return adaptee.translateName(f.getFieldObject());
}
}

View File

@ -86,7 +86,7 @@ public final class Gson {
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
new ModifierBasedExclusionStrategy(new int[] { Modifier.TRANSIENT, Modifier.STATIC });
static final JsonFormatter DEFAULT_JSON_FORMATTER = new JsonCompactFormatter();
static final FieldNamingStrategy DEFAULT_NAMING_POLICY =
static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY =
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY =
@ -98,7 +98,7 @@ public final class Gson {
private final ExclusionStrategy deserializationStrategy;
private final FieldNamingStrategy fieldNamingPolicy;
private final FieldNamingStrategy2 fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor;
/** Map containing Type or Class objects as keys */
@ -154,7 +154,7 @@ public final class Gson {
}
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
FieldNamingStrategy fieldNamingPolicy, MappedObjectConstructor objectConstructor,
FieldNamingStrategy2 fieldNamingPolicy, MappedObjectConstructor objectConstructor,
JsonFormatter formatter, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,

View File

@ -69,7 +69,7 @@ public final class GsonBuilder {
private boolean serializeInnerClasses;
private boolean excludeFieldsWithoutExposeAnnotation;
private LongSerializationPolicy longSerializationPolicy;
private FieldNamingStrategy fieldNamingPolicy;
private FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators;
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
@ -220,8 +220,22 @@ public final class GsonBuilder {
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
* @deprecated use {@link #setFieldNamingStrategy(FieldNamingStrategy2)} instead.
*/
@Deprecated
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
return setFieldNamingStrategy(new FieldNamingStrategy2Adapter(fieldNamingStrategy));
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
*/
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy2 fieldNamingStrategy) {
this.fieldNamingPolicy =
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
return this;

View File

@ -18,6 +18,7 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A simple implementation of the {@link FieldNamingStrategy} interface such that it does not
@ -44,7 +45,7 @@ import java.lang.reflect.Type;
class JavaFieldNamingPolicy extends RecursiveFieldNamingPolicy {
@Override
protected String translateName(String target, Type fieldType, Annotation[] annotations) {
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
return target;
}
}

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
/**
@ -91,17 +90,17 @@ final class JsonArrayDeserializationVisitor<T> extends JsonDeserializationVisito
throw new JsonParseException("Expecting array but found object: " + node);
}
public void visitArrayField(Field f, Type typeOfF, Object obj) {
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
throw new JsonParseException("Expecting array but found array field " + f.getName() + ": "
+ obj);
}
public void visitObjectField(Field f, Type typeOfF, Object obj) {
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
throw new JsonParseException("Expecting array but found object field " + f.getName() + ": "
+ obj);
}
public boolean visitFieldUsingCustomHandler(Field f, Type actualTypeOfField, Object parent) {
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField, Object parent) {
throw new JsonParseException("Expecting array but found field " + f.getName() + ": "
+ parent);
}

View File

@ -16,7 +16,6 @@
package com.google.gson;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
/**
@ -50,7 +49,7 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
throw new JsonParseException("Expecting object but found array: " + array);
}
public void visitObjectField(Field f, Type typeOfF, Object obj) {
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (!json.isJsonObject()) {
throw new JsonParseException("Expecting object found: " + json);
@ -69,7 +68,7 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
}
}
public void visitArrayField(Field f, Type typeOfF, Object obj) {
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (!json.isJsonObject()) {
throw new JsonParseException("Expecting object found: " + json);
@ -88,12 +87,12 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
}
}
private String getFieldName(Field f) {
FieldNamingStrategy namingPolicy = factory.getFieldNamingPolicy();
private String getFieldName(FieldAttributes f) {
FieldNamingStrategy2 namingPolicy = factory.getFieldNamingPolicy();
return namingPolicy.translateName(f);
}
public boolean visitFieldUsingCustomHandler(Field f, Type declaredTypeOfField, Object parent) {
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type declaredTypeOfField, Object parent) {
try {
String fName = getFieldName(f);
if (!json.isJsonObject()) {

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
/**
@ -84,7 +83,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
}
}
public void visitArrayField(Field f, Type typeOfF, Object obj) {
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (isFieldNull(f, obj)) {
if (serializeNulls) {
@ -99,7 +98,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
}
}
public void visitObjectField(Field f, Type typeOfF, Object obj) {
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (isFieldNull(f, obj)) {
if (serializeNulls) {
@ -122,13 +121,13 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
assignToRoot(json);
}
private void addAsChildOfObject(Field f, ObjectTypePair fieldValuePair) {
private void addAsChildOfObject(FieldAttributes f, ObjectTypePair fieldValuePair) {
JsonElement childElement = getJsonElementForChild(fieldValuePair);
addChildAsElement(f, childElement);
}
private void addChildAsElement(Field f, JsonElement childElement) {
FieldNamingStrategy namingPolicy = factory.getFieldNamingPolicy();
private void addChildAsElement(FieldAttributes f, JsonElement childElement) {
FieldNamingStrategy2 namingPolicy = factory.getFieldNamingPolicy();
root.getAsJsonObject().add(namingPolicy.translateName(f), childElement);
}
@ -191,7 +190,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
}
}
public boolean visitFieldUsingCustomHandler(Field f, Type declaredTypeOfField, Object parent) {
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type declaredTypeOfField, Object parent) {
try {
Preconditions.checkState(root.isJsonObject());
Object obj = f.get(parent);
@ -221,11 +220,11 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
root = newRoot;
}
private boolean isFieldNull(Field f, Object obj) {
private boolean isFieldNull(FieldAttributes f, Object obj) {
return getFieldValue(f, obj) == null;
}
private Object getFieldValue(Field f, Object obj) {
private Object getFieldValue(FieldAttributes f, Object obj) {
try {
return f.get(obj);
} catch (IllegalAccessException e) {

View File

@ -18,12 +18,13 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A {@link FieldNamingStrategy} that ensures the JSON field names consist of only
* lower case letters.
*
*<p>The following is an example:</p>
* <p>The following is an example:</p>
* <pre>
* class IntWrapper {
* public int integerField = 0;
@ -36,12 +37,14 @@ import java.lang.reflect.Type;
* assert("integerfield".equals(translatedFieldName));
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
class LowerCaseNamingPolicy extends RecursiveFieldNamingPolicy {
@Override
protected String translateName(String target, Type fieldType, Annotation[] annotations) {
protected String translateName(String target, Type fieldType,
Collection<Annotation> annotations) {
return target.toLowerCase();
}
}

View File

@ -18,6 +18,7 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A {@link FieldNamingStrategy} that ensures the JSON field names begins with
@ -67,7 +68,8 @@ class ModifyFirstLetterNamingPolicy extends RecursiveFieldNamingPolicy {
}
@Override
protected String translateName(String target, Type fieldType, Annotation[] annotations) {
protected String translateName(String target, Type fieldType,
Collection<Annotation> annotations) {
StringBuilder fieldNameBuilder = new StringBuilder();
int index = 0;
char firstCharacter = target.charAt(index);

View File

@ -21,8 +21,9 @@ import java.lang.reflect.Field;
import java.lang.reflect.Type;
/**
* Provides ability to apply a visitor to an object and all of its fields recursively.
*
* Provides ability to apply a visitor to an object and all of its fields
* recursively.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
@ -30,10 +31,12 @@ final class ObjectNavigator {
public interface Visitor {
public void start(ObjectTypePair node);
public void end(ObjectTypePair node);
/**
* This is called before the object navigator starts visiting the current object
* This is called before the object navigator starts visiting the current
* object
*/
void startVisitingObject(Object node);
@ -45,23 +48,26 @@ final class ObjectNavigator {
/**
* This is called to visit an object field of the current object
*/
void visitObjectField(Field f, Type typeOfF, Object obj);
void visitObjectField(FieldAttributes f, Type typeOfF, Object obj);
/**
* This is called to visit an array field of the current object
*/
void visitArrayField(Field f, Type typeOfF, Object obj);
void visitArrayField(FieldAttributes f, Type typeOfF, Object obj);
/**
* This is called to visit an object using a custom handler
*
* @return true if a custom handler exists, false otherwise
*/
public boolean visitUsingCustomHandler(ObjectTypePair objTypePair);
/**
* This is called to visit a field of the current object using a custom handler
* This is called to visit a field of the current object using a custom
* handler
*/
public boolean visitFieldUsingCustomHandler(Field f, Type actualTypeOfField, Object parent);
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField,
Object parent);
/**
* Retrieve the current target
@ -75,9 +81,11 @@ final class ObjectNavigator {
private final ObjectTypePair objTypePair;
/**
* @param objTypePair The object,type (fully genericized) being navigated
* @param exclusionStrategy the concrete strategy object to be used to
* filter out fields of an object.
* @param objTypePair
* The object,type (fully genericized) being navigated
* @param exclusionStrategy
* the concrete strategy object to be used to filter out fields of an
* object.
*/
ObjectNavigator(ObjectTypePair objTypePair, ExclusionStrategy exclusionStrategy) {
Preconditions.checkNotNull(exclusionStrategy);
@ -87,8 +95,8 @@ final class ObjectNavigator {
}
/**
* Navigate all the fields of the specified object.
* If a field is null, it does not get visited.
* Navigate all the fields of the specified object. If a field is null, it
* does not get visited.
*/
public void accept(Visitor visitor) {
TypeInfo objTypeInfo = new TypeInfo(objTypePair.type);
@ -110,15 +118,15 @@ final class ObjectNavigator {
} else if (objTypeInfo.getActualType() == Object.class
&& isPrimitiveOrString(objectToVisit)) {
// TODO(Joel): this is only used for deserialization of "primitives"
// we should rethink this!!!
// we should rethink this!!!
visitor.visitPrimitive(objectToVisit);
objectToVisit = visitor.getTarget();
} else {
visitor.startVisitingObject(objectToVisit);
ObjectTypePair currObjTypePair = objTypePair.toMoreSpecificType();
Class<?> topLevelClass = new TypeInfo(currObjTypePair.type).getRawClass();
for (Class<?> curr = topLevelClass; curr != null && !curr.equals(Object.class);
curr = curr.getSuperclass()) {
for (Class<?> curr = topLevelClass; curr != null && !curr.equals(Object.class); curr =
curr.getSuperclass()) {
if (!curr.isSynthetic()) {
navigateClassFields(objectToVisit, curr, visitor);
}
@ -148,12 +156,12 @@ final class ObjectNavigator {
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.type);
Type declaredTypeOfField = fieldTypeInfo.getActualType();
boolean visitedWithCustomHandler =
visitor.visitFieldUsingCustomHandler(f, declaredTypeOfField, obj);
visitor.visitFieldUsingCustomHandler(fieldAttributes, declaredTypeOfField, obj);
if (!visitedWithCustomHandler) {
if (fieldTypeInfo.isArray()) {
visitor.visitArrayField(f, declaredTypeOfField, obj);
visitor.visitArrayField(fieldAttributes, declaredTypeOfField, obj);
} else {
visitor.visitObjectField(f, declaredTypeOfField, obj);
visitor.visitObjectField(fieldAttributes, declaredTypeOfField, obj);
}
}
}

View File

@ -25,7 +25,7 @@ package com.google.gson;
*/
final class ObjectNavigatorFactory {
private final ExclusionStrategy strategy;
private final FieldNamingStrategy fieldNamingPolicy;
private final FieldNamingStrategy2 fieldNamingPolicy;
/**
* Creates a factory object that will be able to create new
@ -36,7 +36,7 @@ final class ObjectNavigatorFactory {
* @param fieldNamingPolicy the naming policy that should be applied to field
* names
*/
public ObjectNavigatorFactory(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) {
public ObjectNavigatorFactory(ExclusionStrategy strategy, FieldNamingStrategy2 fieldNamingPolicy) {
Preconditions.checkNotNull(fieldNamingPolicy);
this.strategy = (strategy == null ? new NullExclusionStrategy() : strategy);
this.fieldNamingPolicy = fieldNamingPolicy;
@ -55,7 +55,7 @@ final class ObjectNavigatorFactory {
return new ObjectNavigator(objTypePair, strategy);
}
FieldNamingStrategy getFieldNamingPolicy() {
FieldNamingStrategy2 getFieldNamingPolicy() {
return fieldNamingPolicy;
}
}

View File

@ -13,8 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
/**
* A simple object that holds onto a pair of object references, first and second.
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <FIRST>
* @param <SECOND>
*/
final class Pair<FIRST, SECOND> {
final FIRST first;
@ -24,4 +34,24 @@ final class Pair<FIRST, SECOND> {
this.first = first;
this.second = second;
}
}
@Override
public int hashCode() {
return 17 * ((first != null) ? first.hashCode() : 0)
+ 17 * ((second != null) ? second.hashCode() : 0);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair<?, ?>)) {
return false;
}
Pair<?, ?> that = (Pair<?, ?>) o;
return equal(this.first, that.first) && equal(this.second, that.second);
}
private static boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
}

View File

@ -17,8 +17,8 @@
package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
@ -27,11 +27,11 @@ import java.lang.reflect.Type;
*
* @author Joel Leitch
*/
abstract class RecursiveFieldNamingPolicy implements FieldNamingStrategy {
abstract class RecursiveFieldNamingPolicy implements FieldNamingStrategy2 {
public final String translateName(Field f) {
public final String translateName(FieldAttributes f) {
Preconditions.checkNotNull(f);
return translateName(f.getName(), f.getGenericType(), f.getAnnotations());
return translateName(f.getName(), f.getDeclaredType(), f.getAnnotations());
}
/**
@ -42,5 +42,5 @@ abstract class RecursiveFieldNamingPolicy implements FieldNamingStrategy {
* @param annotations the annotations set on the field
* @return the translated field name
*/
protected abstract String translateName(String target, Type fieldType, Annotation[] annotations);
protected abstract String translateName(String target, Type fieldType, Collection<Annotation> annotations);
}

View File

@ -18,8 +18,6 @@ package com.google.gson;
import com.google.gson.annotations.SerializedName;
import java.lang.reflect.Field;
/**
* A {@link FieldNamingStrategy} that acts as a chain of responsibility. If the
* {@link com.google.gson.annotations.SerializedName} annotation is applied to a field then this
@ -33,15 +31,15 @@ import java.lang.reflect.Field;
*
* @author Joel Leitch
*/
final class SerializedNameAnnotationInterceptingNamingPolicy implements FieldNamingStrategy {
final class SerializedNameAnnotationInterceptingNamingPolicy implements FieldNamingStrategy2 {
private static final JsonFieldNameValidator fieldNameValidator = new JsonFieldNameValidator();
private final FieldNamingStrategy delegate;
private final FieldNamingStrategy2 delegate;
public SerializedNameAnnotationInterceptingNamingPolicy(FieldNamingStrategy delegate) {
public SerializedNameAnnotationInterceptingNamingPolicy(FieldNamingStrategy2 delegate) {
this.delegate = delegate;
}
public String translateName(Field f) {
public String translateName(FieldAttributes f) {
Preconditions.checkNotNull(f);
SerializedName serializedName = f.getAnnotation(SerializedName.class);
if (serializedName != null) {

View File

@ -18,6 +18,7 @@ package com.google.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A {@link FieldNamingStrategy} that ensures the JSON field names consist of only
@ -41,7 +42,7 @@ import java.lang.reflect.Type;
class UpperCaseNamingPolicy extends RecursiveFieldNamingPolicy {
@Override
protected String translateName(String target, Type fieldType, Annotation[] annotations) {
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
return target.toUpperCase();
}
}

View File

@ -18,8 +18,6 @@ package com.google.gson;
import junit.framework.TestCase;
import java.lang.reflect.Field;
/**
* Tests for the {@link JavaFieldNamingPolicy} class.
*
@ -36,13 +34,13 @@ public class JavaFieldNamingPolicyTest extends TestCase {
}
public void testFieldNamingPolicy() throws Exception {
Field f = String.class.getFields()[0];
FieldAttributes f = new FieldAttributes(String.class.getFields()[0]);
assertEquals(f.getName(), namingPolicy.translateName(f));
}
public void testNullField() throws Exception {
try {
namingPolicy.translateName((Field) null);
namingPolicy.translateName((FieldAttributes) null);
fail("Should have thrown an exception");
} catch (IllegalArgumentException expected) { }
}

View File

@ -16,11 +16,9 @@
package com.google.gson;
import com.google.gson.annotations.SerializedName;
import junit.framework.TestCase;
import java.lang.reflect.Field;
import com.google.gson.annotations.SerializedName;
/**
* Unit tests for the {@link SerializedNameAnnotationInterceptingNamingPolicy} class.
@ -40,7 +38,7 @@ public class SerializedNameAnnotationInterceptingNamingPolicyTest extends TestCa
public void testFieldWithAnnotation() throws Exception {
String fieldName = "fieldWithAnnotation";
Field f = SomeObject.class.getField(fieldName);
FieldAttributes f = new FieldAttributes(SomeObject.class.getField(fieldName));
assertFalse(ANNOTATED_FIELD_NAME.equals(fieldName));
assertEquals(ANNOTATED_FIELD_NAME, policy.translateName(f));
@ -48,7 +46,7 @@ public class SerializedNameAnnotationInterceptingNamingPolicyTest extends TestCa
public void testFieldWithoutAnnotation() throws Exception {
String fieldName = "fieldWithoutAnnotation";
Field f = SomeObject.class.getField(fieldName);
FieldAttributes f = new FieldAttributes(SomeObject.class.getField(fieldName));
assertEquals(fieldName, policy.translateName(f));
}

View File

@ -426,7 +426,6 @@ public class CustomTypeAdaptersTest extends TestCase {
}
private static class DataHolder {
@SuppressWarnings("unused")
final String data;
// For use by Gson