Refactored exclusion strategies so that they can easily be exposed as part of the public API.
This commit is contained in:
parent
c892738fbb
commit
839b0c2f94
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy for excluding anonymous and local classes.
|
* Strategy for excluding anonymous and local classes.
|
||||||
@ -25,8 +24,8 @@ import java.lang.reflect.Field;
|
|||||||
*/
|
*/
|
||||||
final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
|
final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
return isAnonymousOrLocal(f.getType());
|
return isAnonymousOrLocal(f.getDeclaredClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,7 +32,7 @@ final class DisjunctionExclusionStrategy implements ExclusionStrategy {
|
|||||||
this.strategies = strategies;
|
this.strategies = strategies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
for (ExclusionStrategy strategy : strategies) {
|
for (ExclusionStrategy strategy : strategies) {
|
||||||
if (strategy.shouldSkipField(f)) {
|
if (strategy.shouldSkipField(f)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -16,31 +16,55 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy definition that is used by the {@link ObjectNavigator} to
|
* A strategy pattern (see "Design Patterns" written by GoF for some literature on this pattern)
|
||||||
* determine whether or not the field of the object should be ignored during
|
* definition that is used to decide whether or not a field or top-level class should be serialized
|
||||||
* navigation.
|
* (or deserialized) as part of the JSON output/input.
|
||||||
*
|
*
|
||||||
* As well, for now this class is also responsible for excluding entire
|
* <p>The following example show an implementation of an {@code ExclusionStrategy} where a specific
|
||||||
* classes. This is somewhat a mixing of concerns for this object, but
|
* type will be excluded from the output.
|
||||||
* it will suffice for now. We can always break it down into two
|
|
||||||
* different strategies later.
|
|
||||||
*
|
*
|
||||||
|
* <p><pre class="code">
|
||||||
|
* private static class UserDefinedExclusionStrategy implements ExclusionStrategy {
|
||||||
|
* private final Class<?> excludedThisClass;
|
||||||
|
*
|
||||||
|
* UserDefinedExclusionStrategy(Class<?> excludedThisClass) {
|
||||||
|
* this.excludedThisClass = excludedThisClass;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
* return excludedThisClass.equals(clazz);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
* return excludedThisClass.equals(f.getDeclaredClass());
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||||
|
* Gson gson = new GsonBuilder()
|
||||||
|
* .setExclusionStrategies(excludeStrings)
|
||||||
|
* .create();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
|
*
|
||||||
|
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
interface ExclusionStrategy {
|
interface ExclusionStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param f the field object that is under test
|
* @param f the field object that is under test
|
||||||
* @return true if the field should be ignored otherwise false
|
* @return true if the field should be ignored; otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean shouldSkipField(Field f);
|
public boolean shouldSkipField(FieldAttributes f);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clazz the class object that is under test
|
* @param clazz the class object that is under test
|
||||||
* @return true if the class should be ignored otherwise false
|
* @return true if the class should be ignored; otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean shouldSkipClass(Class<?> clazz);
|
public boolean shouldSkipClass(Class<?> clazz);
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excludes fields that do not have the {@link Expose} annotation
|
* Excludes fields that do not have the {@link Expose} annotation
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@ -31,7 +29,7 @@ final class ExposeAnnotationDeserializationExclusionStrategy implements Exclusio
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
Expose annotation = f.getAnnotation(Expose.class);
|
Expose annotation = f.getAnnotation(Expose.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -18,11 +18,9 @@ package com.google.gson;
|
|||||||
|
|
||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excludes fields that do not have the {@link Expose} annotation
|
* Excludes fields that do not have the {@link Expose} annotation
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@ -32,7 +30,7 @@ final class ExposeAnnotationSerializationExclusionStrategy implements ExclusionS
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
Expose annotation = f.getAnnotation(Expose.class);
|
Expose annotation = f.getAnnotation(Expose.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
return true;
|
return true;
|
||||||
|
124
gson/src/main/java/com/google/gson/FieldAttributes.java
Normal file
124
gson/src/main/java/com/google/gson/FieldAttributes.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data object that stores attributes of a field.
|
||||||
|
*
|
||||||
|
* <p>This class is immutable; therefore, it can be safely shared across threads.
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
* @author Joel Leitch
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
final class FieldAttributes {
|
||||||
|
private final Field field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Field Attributes object
|
||||||
|
* @param f
|
||||||
|
*/
|
||||||
|
FieldAttributes(Field f) {
|
||||||
|
Preconditions.checkNotNull(f);
|
||||||
|
field = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of the field
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return field.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>For example, assume the following class definition:
|
||||||
|
* <pre class="code">
|
||||||
|
* public class Foo {
|
||||||
|
* private String bar;
|
||||||
|
* private List<String> red;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||||
|
* {@code listParameterizedType} for the {@code red} field.
|
||||||
|
*
|
||||||
|
* @return the specific type declared for this field
|
||||||
|
*/
|
||||||
|
public Type getDeclaredType() {
|
||||||
|
return field.getGenericType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@code Class<?>} object that was declared for this field.
|
||||||
|
*
|
||||||
|
* <p>For example, assume the following class definition:
|
||||||
|
* <pre class="code">
|
||||||
|
* public class Foo {
|
||||||
|
* private String bar;
|
||||||
|
* private List<String> red;
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||||
|
* {@code List.class} for the {@code red} field.
|
||||||
|
*
|
||||||
|
* @return the specific class object that was declared for the field
|
||||||
|
*/
|
||||||
|
public Class<?> getDeclaredClass() {
|
||||||
|
return field.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link T} annotation object from this field if it exist; otherwise returns
|
||||||
|
* {@code null}.
|
||||||
|
*
|
||||||
|
* @param annotation the class of the annotation that will be retrieved
|
||||||
|
* @return the annotation instance if it is bound to the field; otherwise {@code null}
|
||||||
|
*/
|
||||||
|
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
|
||||||
|
return field.getAnnotation(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the field is defined with the {@code modifier}.
|
||||||
|
*
|
||||||
|
* <p>This method is meant to be called as:
|
||||||
|
* <pre class="code">
|
||||||
|
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see java.lang.reflect.Modifier
|
||||||
|
*/
|
||||||
|
public boolean hasModifier(int modifier) {
|
||||||
|
return (field.getModifiers() & modifier) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is exposed internally only for the
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isSynthetic() {
|
||||||
|
return field.isSynthetic();
|
||||||
|
}
|
||||||
|
}
|
@ -77,20 +77,27 @@ public final class Gson {
|
|||||||
private static final String NULL_STRING = "null";
|
private static final String NULL_STRING = "null";
|
||||||
|
|
||||||
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 =
|
||||||
|
new AnonymousAndLocalClassExclusionStrategy();
|
||||||
|
static final SyntheticFieldExclusionStrategy DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY =
|
||||||
|
new SyntheticFieldExclusionStrategy(true);
|
||||||
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
|
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
|
||||||
new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC });
|
new ModifierBasedExclusionStrategy(new int[] { Modifier.TRANSIENT, Modifier.STATIC });
|
||||||
static final JsonFormatter DEFAULT_JSON_FORMATTER = new JsonCompactFormatter();
|
static final JsonFormatter DEFAULT_JSON_FORMATTER = new JsonCompactFormatter();
|
||||||
static final FieldNamingStrategy DEFAULT_NAMING_POLICY =
|
static final FieldNamingStrategy DEFAULT_NAMING_POLICY =
|
||||||
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
|
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
|
||||||
|
|
||||||
|
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY =
|
||||||
|
createExclusionStrategy(VersionConstants.IGNORE_VERSIONS);
|
||||||
|
|
||||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||||
|
|
||||||
private final ExclusionStrategy serializationStrategy;
|
private final ExclusionStrategy serializationStrategy;
|
||||||
|
|
||||||
private final ExclusionStrategy deserializationStrategy;
|
private final ExclusionStrategy deserializationStrategy;
|
||||||
|
|
||||||
private final FieldNamingStrategy fieldNamingPolicy;
|
private final FieldNamingStrategy fieldNamingPolicy;
|
||||||
private final MappedObjectConstructor objectConstructor;
|
private final MappedObjectConstructor objectConstructor;
|
||||||
|
|
||||||
@ -121,7 +128,7 @@ public final class Gson {
|
|||||||
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
|
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
|
||||||
* to change the default representation, you can do so by registering a type adapter through
|
* to change the default representation, you can do so by registering a type adapter through
|
||||||
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
|
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
|
||||||
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
|
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
|
||||||
* ignores the millisecond portion of the date during serialization. You can change
|
* ignores the millisecond portion of the date during serialization. You can change
|
||||||
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
|
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
|
||||||
* {@link GsonBuilder#setDateFormat(String)}. </li>
|
* {@link GsonBuilder#setDateFormat(String)}. </li>
|
||||||
@ -140,25 +147,17 @@ public final class Gson {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public Gson() {
|
public Gson() {
|
||||||
this(createExclusionStrategy(VersionConstants.IGNORE_VERSIONS), DEFAULT_NAMING_POLICY);
|
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
|
||||||
|
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
||||||
|
DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(),
|
||||||
|
DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
||||||
* Constructs a Gson object with the specified version and the mode of operation while
|
FieldNamingStrategy fieldNamingPolicy, MappedObjectConstructor objectConstructor,
|
||||||
* encountering inner class references.
|
JsonFormatter formatter, boolean serializeNulls,
|
||||||
*/
|
|
||||||
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) {
|
|
||||||
this(strategy, strategy, fieldNamingPolicy,
|
|
||||||
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
|
||||||
DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(),
|
|
||||||
DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy,
|
|
||||||
FieldNamingStrategy fieldNamingPolicy, MappedObjectConstructor objectConstructor,
|
|
||||||
JsonFormatter formatter, boolean serializeNulls,
|
|
||||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
|
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
|
||||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||||
boolean generateNonExecutableGson) {
|
boolean generateNonExecutableGson) {
|
||||||
this.serializationStrategy = serializationStrategy;
|
this.serializationStrategy = serializationStrategy;
|
||||||
this.deserializationStrategy = deserializationStrategy;
|
this.deserializationStrategy = deserializationStrategy;
|
||||||
@ -170,14 +169,15 @@ public final class Gson {
|
|||||||
this.deserializers = deserializers;
|
this.deserializers = deserializers;
|
||||||
this.generateNonExecutableJson = generateNonExecutableGson;
|
this.generateNonExecutableJson = generateNonExecutableGson;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy strategy) {
|
private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy strategy) {
|
||||||
return new ObjectNavigatorFactory(strategy, fieldNamingPolicy);
|
return new ObjectNavigatorFactory(strategy, fieldNamingPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExclusionStrategy createExclusionStrategy(double version) {
|
private static ExclusionStrategy createExclusionStrategy(double version) {
|
||||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||||
strategies.add(new AnonymousAndLocalClassExclusionStrategy());
|
strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
|
||||||
|
strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
|
||||||
strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
|
strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
|
||||||
if (version != VersionConstants.IGNORE_VERSIONS) {
|
if (version != VersionConstants.IGNORE_VERSIONS) {
|
||||||
strategies.add(new VersionExclusionStrategy(version));
|
strategies.add(new VersionExclusionStrategy(version));
|
||||||
@ -186,7 +186,7 @@ public final class Gson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method serializes the specified object into its equivalent representation as a tree of
|
* This method serializes the specified object into its equivalent representation as a tree of
|
||||||
* {@link JsonElement}s. This method should be used when the specified object is not a generic
|
* {@link JsonElement}s. This method should be used when the specified object is not a generic
|
||||||
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
|
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
|
||||||
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
|
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
|
||||||
@ -207,9 +207,9 @@ public final class Gson {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method serializes the specified object, including those of generic types, into its
|
* This method serializes the specified object, including those of generic types, into its
|
||||||
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
|
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
|
||||||
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
|
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
|
||||||
* instead.
|
* instead.
|
||||||
*
|
*
|
||||||
* @param src the object for which JSON representation is to be created
|
* @param src the object for which JSON representation is to be created
|
||||||
* @param typeOfSrc The specific genericized type of src. You can obtain
|
* @param typeOfSrc The specific genericized type of src. You can obtain
|
||||||
@ -318,7 +318,7 @@ public final class Gson {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
||||||
*
|
*
|
||||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||||
* @return JSON String representation of the tree
|
* @return JSON String representation of the tree
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
@ -328,10 +328,10 @@ public final class Gson {
|
|||||||
toJson(jsonElement, writer);
|
toJson(jsonElement, writer);
|
||||||
return writer.toString();
|
return writer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
|
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
|
||||||
*
|
*
|
||||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||||
* @param writer Writer to which the Json representation needs to be written
|
* @param writer Writer to which the Json representation needs to be written
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
@ -347,7 +347,7 @@ public final class Gson {
|
|||||||
formatter.format(jsonElement, writer, serializeNulls);
|
formatter.format(jsonElement, writer, serializeNulls);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -452,9 +452,9 @@ public final class Gson {
|
|||||||
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
||||||
* this method works fine if the any of the fields of the specified object are generics, just the
|
* this method works fine if the any of the fields of the specified object are generics, just the
|
||||||
* object itself should not be a generic type. For the cases when the object is of generic type,
|
* object itself should not be a generic type. For the cases when the object is of generic type,
|
||||||
* invoke {@link #fromJson(JsonElement, Type)}.
|
* invoke {@link #fromJson(JsonElement, Type)}.
|
||||||
* @param <T> the type of the desired object
|
* @param <T> the type of the desired object
|
||||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||||
* be deserialized
|
* be deserialized
|
||||||
* @param classOfT The class of T
|
* @param classOfT The class of T
|
||||||
* @return an object of type T from the json
|
* @return an object of type T from the json
|
||||||
@ -469,10 +469,10 @@ public final class Gson {
|
|||||||
/**
|
/**
|
||||||
* This method deserializes the Json read from the specified parse tree into an object of the
|
* This method deserializes the Json read from the specified parse tree into an object of the
|
||||||
* specified type. This method is useful if the specified object is a generic type. For
|
* specified type. This method is useful if the specified object is a generic type. For
|
||||||
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
|
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
|
||||||
*
|
*
|
||||||
* @param <T> the type of the desired object
|
* @param <T> the type of the desired object
|
||||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||||
* be deserialized
|
* be deserialized
|
||||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||||
* {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
|
* {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for
|
||||||
@ -490,7 +490,7 @@ public final class Gson {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JsonDeserializationContext context = new JsonDeserializationContextDefault(
|
JsonDeserializationContext context = new JsonDeserializationContextDefault(
|
||||||
createDefaultObjectNavigatorFactory(deserializationStrategy), deserializers,
|
createDefaultObjectNavigatorFactory(deserializationStrategy), deserializers,
|
||||||
objectConstructor);
|
objectConstructor);
|
||||||
T target = (T) context.deserialize(json, typeOfT);
|
T target = (T) context.deserialize(json, typeOfT);
|
||||||
return target;
|
return target;
|
||||||
@ -504,15 +504,15 @@ public final class Gson {
|
|||||||
private void writeOutNullString(Appendable writer) throws IOException {
|
private void writeOutNullString(Appendable writer) throws IOException {
|
||||||
writer.append(NULL_STRING);
|
writer.append(NULL_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder("{")
|
StringBuilder sb = new StringBuilder("{")
|
||||||
.append("serializeNulls:").append(serializeNulls)
|
.append("serializeNulls:").append(serializeNulls)
|
||||||
.append(",serializers:").append(serializers)
|
.append(",serializers:").append(serializers)
|
||||||
.append(",deserializers:").append(deserializers)
|
.append(",deserializers:").append(deserializers)
|
||||||
|
|
||||||
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
|
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
|
||||||
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
|
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
|
||||||
// just a utility class around instance creators, and its toString() only displays them.
|
// just a utility class around instance creators, and its toString() only displays them.
|
||||||
.append(",instanceCreators:").append(objectConstructor)
|
.append(",instanceCreators:").append(objectConstructor)
|
||||||
|
@ -18,7 +18,9 @@ package com.google.gson;
|
|||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -50,17 +52,18 @@ import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class GsonBuilder {
|
public final class GsonBuilder {
|
||||||
private static final AnonymousAndLocalClassExclusionStrategy anonAndLocalClassExclusionStrategy =
|
|
||||||
new AnonymousAndLocalClassExclusionStrategy();
|
|
||||||
private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
|
private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
|
||||||
new InnerClassExclusionStrategy();
|
new InnerClassExclusionStrategy();
|
||||||
private static final ExposeAnnotationSerializationExclusionStrategy
|
private static final ExposeAnnotationSerializationExclusionStrategy
|
||||||
exposeAnnotationSerializationExclusionStrategy =
|
exposeAnnotationSerializationExclusionStrategy =
|
||||||
new ExposeAnnotationSerializationExclusionStrategy();
|
new ExposeAnnotationSerializationExclusionStrategy();
|
||||||
private static final ExposeAnnotationDeserializationExclusionStrategy
|
private static final ExposeAnnotationDeserializationExclusionStrategy
|
||||||
exposeAnnotationDeserializationExclusionStrategy =
|
exposeAnnotationDeserializationExclusionStrategy =
|
||||||
new ExposeAnnotationDeserializationExclusionStrategy();
|
new ExposeAnnotationDeserializationExclusionStrategy();
|
||||||
|
|
||||||
|
private final Collection<ExclusionStrategy> exclusionStrategies =
|
||||||
|
new HashSet<ExclusionStrategy>();
|
||||||
|
|
||||||
private double ignoreVersionsAfter;
|
private double ignoreVersionsAfter;
|
||||||
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
|
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
|
||||||
private boolean serializeInnerClasses;
|
private boolean serializeInnerClasses;
|
||||||
@ -86,6 +89,10 @@ public final class GsonBuilder {
|
|||||||
* {@link #create()}.
|
* {@link #create()}.
|
||||||
*/
|
*/
|
||||||
public GsonBuilder() {
|
public GsonBuilder() {
|
||||||
|
// add default exclusion strategies
|
||||||
|
exclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
|
||||||
|
exclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
|
||||||
|
|
||||||
// setup default values
|
// setup default values
|
||||||
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
|
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
|
||||||
serializeInnerClasses = true;
|
serializeInnerClasses = true;
|
||||||
@ -129,17 +136,16 @@ public final class GsonBuilder {
|
|||||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||||
*/
|
*/
|
||||||
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
|
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
|
||||||
boolean skipSynthetics = true;
|
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
|
||||||
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(skipSynthetics, modifiers);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
|
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
|
||||||
* special text. This prevents attacks from third-party sites through script sourcing. See
|
* special text. This prevents attacks from third-party sites through script sourcing. See
|
||||||
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
|
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
|
||||||
* for details.
|
* for details.
|
||||||
*
|
*
|
||||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
@ -147,7 +153,7 @@ public final class GsonBuilder {
|
|||||||
this.generateNonExecutableJson = true;
|
this.generateNonExecutableJson = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures Gson to exclude all fields from consideration for serialization or deserialization
|
* Configures Gson to exclude all fields from consideration for serialization or deserialization
|
||||||
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
|
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
|
||||||
@ -216,8 +222,25 @@ public final class GsonBuilder {
|
|||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
|
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
|
||||||
this.fieldNamingPolicy =
|
this.fieldNamingPolicy =
|
||||||
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
|
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Gson to apply a set of exclusion strategies during both serialization and
|
||||||
|
* deserialization. Each of the {@code strategies} will be applied as a disjunctive rule.
|
||||||
|
* This means that if one of the {@code strategies} suggests that a field (or class) should be
|
||||||
|
* skipped then that field (or object) is skipped during serializaiton/deserialization.
|
||||||
|
*
|
||||||
|
* @param strategies the set of strategy object to apply during object (de)serialization.
|
||||||
|
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
|
||||||
|
for (ExclusionStrategy strategy : strategies) {
|
||||||
|
exclusionStrategies.add(strategy);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,12 +435,13 @@ public final class GsonBuilder {
|
|||||||
* @return an instance of Gson configured with the options currently set in this builder
|
* @return an instance of Gson configured with the options currently set in this builder
|
||||||
*/
|
*/
|
||||||
public Gson create() {
|
public Gson create() {
|
||||||
List<ExclusionStrategy> serializationStrategies = new LinkedList<ExclusionStrategy>();
|
List<ExclusionStrategy> serializationStrategies =
|
||||||
List<ExclusionStrategy> deserializationStrategies = new LinkedList<ExclusionStrategy>();
|
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||||
|
List<ExclusionStrategy> deserializationStrategies =
|
||||||
|
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||||
|
|
||||||
serializationStrategies.add(modifierBasedExclusionStrategy);
|
serializationStrategies.add(modifierBasedExclusionStrategy);
|
||||||
deserializationStrategies.add(modifierBasedExclusionStrategy);
|
deserializationStrategies.add(modifierBasedExclusionStrategy);
|
||||||
serializationStrategies.add(anonAndLocalClassExclusionStrategy);
|
|
||||||
deserializationStrategies.add(anonAndLocalClassExclusionStrategy);
|
|
||||||
|
|
||||||
if (!serializeInnerClasses) {
|
if (!serializeInnerClasses) {
|
||||||
serializationStrategies.add(innerClassExclusionStrategy);
|
serializationStrategies.add(innerClassExclusionStrategy);
|
||||||
@ -431,9 +455,9 @@ public final class GsonBuilder {
|
|||||||
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
|
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
|
||||||
deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
|
deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
|
||||||
}
|
}
|
||||||
ExclusionStrategy serializationExclusionStrategy =
|
ExclusionStrategy serializationExclusionStrategy =
|
||||||
new DisjunctionExclusionStrategy(serializationStrategies);
|
new DisjunctionExclusionStrategy(serializationStrategies);
|
||||||
ExclusionStrategy deserializationExclusionStrategy =
|
ExclusionStrategy deserializationExclusionStrategy =
|
||||||
new DisjunctionExclusionStrategy(deserializationStrategies);
|
new DisjunctionExclusionStrategy(deserializationStrategies);
|
||||||
|
|
||||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
|
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = serializers.copyOf();
|
||||||
@ -449,17 +473,17 @@ public final class GsonBuilder {
|
|||||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
|
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
|
||||||
instanceCreators.copyOf();
|
instanceCreators.copyOf();
|
||||||
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
|
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
|
||||||
|
|
||||||
customSerializers.makeUnmodifiable();
|
customSerializers.makeUnmodifiable();
|
||||||
customDeserializers.makeUnmodifiable();
|
customDeserializers.makeUnmodifiable();
|
||||||
instanceCreators.makeUnmodifiable();
|
instanceCreators.makeUnmodifiable();
|
||||||
|
|
||||||
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
|
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
|
||||||
|
|
||||||
JsonFormatter formatter = prettyPrinting ?
|
JsonFormatter formatter = prettyPrinting ?
|
||||||
new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars);
|
new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars);
|
||||||
Gson gson = new Gson(serializationExclusionStrategy, deserializationExclusionStrategy,
|
Gson gson = new Gson(serializationExclusionStrategy, deserializationExclusionStrategy,
|
||||||
fieldNamingPolicy, objConstructor, formatter, serializeNulls, customSerializers,
|
fieldNamingPolicy, objConstructor, formatter, serializeNulls, customSerializers,
|
||||||
customDeserializers, generateNonExecutableJson);
|
customDeserializers, generateNonExecutableJson);
|
||||||
return gson;
|
return gson;
|
||||||
}
|
}
|
||||||
@ -476,7 +500,7 @@ public final class GsonBuilder {
|
|||||||
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
|
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
|
||||||
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
|
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dateTypeAdapter != null) {
|
if (dateTypeAdapter != null) {
|
||||||
serializers.register(Date.class, dateTypeAdapter);
|
serializers.register(Date.class, dateTypeAdapter);
|
||||||
deserializers.register(Date.class, dateTypeAdapter);
|
deserializers.register(Date.class, dateTypeAdapter);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,8 +25,8 @@ import java.lang.reflect.Modifier;
|
|||||||
*/
|
*/
|
||||||
class InnerClassExclusionStrategy implements ExclusionStrategy {
|
class InnerClassExclusionStrategy implements ExclusionStrategy {
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
return isInnerClass(f.getType());
|
return isInnerClass(f.getDeclaredClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
@ -37,7 +36,7 @@ class InnerClassExclusionStrategy implements ExclusionStrategy {
|
|||||||
private boolean isInnerClass(Class<?> clazz) {
|
private boolean isInnerClass(Class<?> clazz) {
|
||||||
return clazz.isMemberClass() && !isStatic(clazz);
|
return clazz.isMemberClass() && !isStatic(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStatic(Class<?> clazz) {
|
private boolean isStatic(Class<?> clazz) {
|
||||||
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
@ -28,11 +27,9 @@ import java.util.HashSet;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
|
final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
|
||||||
private final boolean skipSyntheticField;
|
|
||||||
private final Collection<Integer> modifiers;
|
private final Collection<Integer> modifiers;
|
||||||
|
|
||||||
public ModifierBasedExclusionStrategy(boolean skipSyntheticFields, int... modifiers) {
|
public ModifierBasedExclusionStrategy(int... modifiers) {
|
||||||
this.skipSyntheticField = skipSyntheticFields;
|
|
||||||
this.modifiers = new HashSet<Integer>();
|
this.modifiers = new HashSet<Integer>();
|
||||||
if (modifiers != null) {
|
if (modifiers != null) {
|
||||||
for (int modifier : modifiers) {
|
for (int modifier : modifiers) {
|
||||||
@ -41,13 +38,9 @@ final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
if (skipSyntheticField && f.isSynthetic()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int objectModifiers = f.getModifiers();
|
|
||||||
for (int modifier : modifiers) {
|
for (int modifier : modifiers) {
|
||||||
if ((objectModifiers & modifier) != 0) {
|
if (f.hasModifier(modifier)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This acts as a "Null Object" pattern for the {@link ExclusionStrategy}.
|
* This acts as a "Null Object" pattern for the {@link ExclusionStrategy}.
|
||||||
@ -28,7 +27,7 @@ import java.lang.reflect.Field;
|
|||||||
*/
|
*/
|
||||||
final class NullExclusionStrategy implements ExclusionStrategy {
|
final class NullExclusionStrategy implements ExclusionStrategy {
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ final class ObjectNavigator {
|
|||||||
* 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(Field f, Type actualTypeOfField, Object parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the current target
|
* Retrieve the current target
|
||||||
*/
|
*/
|
||||||
@ -102,7 +102,7 @@ final class ObjectNavigator {
|
|||||||
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visitor.start(objTypePair);
|
visitor.start(objTypePair);
|
||||||
try {
|
try {
|
||||||
if (objTypeInfo.isArray()) {
|
if (objTypeInfo.isArray()) {
|
||||||
visitor.visitArray(objectToVisit, objTypePair.getType());
|
visitor.visitArray(objectToVisit, objTypePair.getType());
|
||||||
@ -141,12 +141,12 @@ final class ObjectNavigator {
|
|||||||
Field[] fields = clazz.getDeclaredFields();
|
Field[] fields = clazz.getDeclaredFields();
|
||||||
AccessibleObject.setAccessible(fields, true);
|
AccessibleObject.setAccessible(fields, true);
|
||||||
for (Field f : fields) {
|
for (Field f : fields) {
|
||||||
if (exclusionStrategy.shouldSkipField(f)) {
|
if (exclusionStrategy.shouldSkipField(new FieldAttributes(f))) {
|
||||||
continue; // skip
|
continue; // skip
|
||||||
} else {
|
} else {
|
||||||
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.getType());
|
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.getType());
|
||||||
Type actualTypeOfField = fieldTypeInfo.getActualType();
|
Type actualTypeOfField = fieldTypeInfo.getActualType();
|
||||||
boolean visitedWithCustomHandler =
|
boolean visitedWithCustomHandler =
|
||||||
visitor.visitFieldUsingCustomHandler(f, actualTypeOfField, obj);
|
visitor.visitFieldUsingCustomHandler(f, actualTypeOfField, obj);
|
||||||
if (!visitedWithCustomHandler) {
|
if (!visitedWithCustomHandler) {
|
||||||
if (fieldTypeInfo.isArray()) {
|
if (fieldTypeInfo.isArray()) {
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data object that stores attributes of a field.
|
||||||
|
*
|
||||||
|
* <p>This class is immutable; therefore, it can be safely shared across threads.
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
* @author Joel Leitch
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
class SyntheticFieldExclusionStrategy implements ExclusionStrategy {
|
||||||
|
private final boolean skipSyntheticFields;
|
||||||
|
|
||||||
|
SyntheticFieldExclusionStrategy(boolean skipSyntheticFields) {
|
||||||
|
this.skipSyntheticFields = skipSyntheticFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
return skipSyntheticFields && f.isSynthetic();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,9 +19,6 @@ package com.google.gson;
|
|||||||
import com.google.gson.annotations.Since;
|
import com.google.gson.annotations.Since;
|
||||||
import com.google.gson.annotations.Until;
|
import com.google.gson.annotations.Until;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This strategy will exclude any files and/or class that are passed the
|
* This strategy will exclude any files and/or class that are passed the
|
||||||
* {@link #version} value.
|
* {@link #version} value.
|
||||||
@ -36,36 +33,31 @@ final class VersionExclusionStrategy implements ExclusionStrategy {
|
|||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
return !isValidVersion(f.getAnnotations());
|
return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
return !isValidVersion(clazz.getAnnotations());
|
return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidVersion(Annotation[] annotations) {
|
private boolean isValidVersion(Since since, Until until) {
|
||||||
for (Annotation annotation : annotations) {
|
return (isValidSince(since) && isValidUntil(until));
|
||||||
if (!isValidSince(annotation) || !isValidUntil(annotation)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidSince(Annotation annotation) {
|
private boolean isValidSince(Since annotation) {
|
||||||
if (annotation instanceof Since) {
|
if (annotation != null) {
|
||||||
double annotationVersion = ((Since) annotation).value();
|
double annotationVersion = annotation.value();
|
||||||
if (annotationVersion > version) {
|
if (annotationVersion > version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidUntil(Annotation annotation) {
|
private boolean isValidUntil(Until annotation) {
|
||||||
if (annotation instanceof Until) {
|
if (annotation != null) {
|
||||||
double annotationVersion = ((Until) annotation).value();
|
double annotationVersion = annotation.value();
|
||||||
if (annotationVersion <= version) {
|
if (annotationVersion <= version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,11 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.DisjunctionExclusionStrategy;
|
|
||||||
import com.google.gson.ExclusionStrategy;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the {@link DisjunctionExclusionStrategy} class.
|
* Unit tests for the {@link DisjunctionExclusionStrategy} class.
|
||||||
*
|
*
|
||||||
@ -35,12 +31,13 @@ public class DisjunctionExclusionStrategyTest extends TestCase {
|
|||||||
private static final ExclusionStrategy FALSE_STRATEGY = new MockExclusionStrategy(false, false);
|
private static final ExclusionStrategy FALSE_STRATEGY = new MockExclusionStrategy(false, false);
|
||||||
private static final ExclusionStrategy TRUE_STRATEGY = new MockExclusionStrategy(true, true);
|
private static final ExclusionStrategy TRUE_STRATEGY = new MockExclusionStrategy(true, true);
|
||||||
private static final Class<?> CLAZZ = String.class;
|
private static final Class<?> CLAZZ = String.class;
|
||||||
private static final Field FIELD = CLAZZ.getFields()[0];
|
private static final FieldAttributes FIELD = new FieldAttributes(CLAZZ.getFields()[0]);
|
||||||
|
|
||||||
public void testBadInstantiation() throws Exception {
|
public void testBadInstantiation() throws Exception {
|
||||||
try {
|
try {
|
||||||
List<ExclusionStrategy> constructorParam = null;
|
List<ExclusionStrategy> constructorParam = null;
|
||||||
new DisjunctionExclusionStrategy(constructorParam);
|
new DisjunctionExclusionStrategy(constructorParam);
|
||||||
|
fail("Should throw an exception");
|
||||||
} catch (IllegalArgumentException expected) { }
|
} catch (IllegalArgumentException expected) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,25 +39,25 @@ public class ExposeAnnotationDeserializationExclusionStrategyTest extends TestCa
|
|||||||
public void testNeverSkipClasses() throws Exception {
|
public void testNeverSkipClasses() throws Exception {
|
||||||
assertFalse(strategy.shouldSkipClass(MockObject.class));
|
assertFalse(strategy.shouldSkipClass(MockObject.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSkipNonAnnotatedFields() throws Exception {
|
public void testSkipNonAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("hiddenField");
|
Field f = MockObject.class.getField("hiddenField");
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSkipExplicitlySkippedFields() throws Exception {
|
public void testSkipExplicitlySkippedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("explicitlyHiddenField");
|
Field f = MockObject.class.getField("explicitlyHiddenField");
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNeverSkipExposedAnnotatedFields() throws Exception {
|
public void testNeverSkipExposedAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("exposedField");
|
Field f = MockObject.class.getField("exposedField");
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception {
|
public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("explicitlyExposedField");
|
Field f = MockObject.class.getField("explicitlyExposedField");
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -67,7 +67,7 @@ public class ExposeAnnotationDeserializationExclusionStrategyTest extends TestCa
|
|||||||
|
|
||||||
@Expose(deserialize=true)
|
@Expose(deserialize=true)
|
||||||
public final int explicitlyExposedField = 0;
|
public final int explicitlyExposedField = 0;
|
||||||
|
|
||||||
@Expose(deserialize=false)
|
@Expose(deserialize=false)
|
||||||
public final int explicitlyHiddenField = 0;
|
public final int explicitlyHiddenField = 0;
|
||||||
|
|
||||||
|
@ -39,25 +39,25 @@ public class ExposeAnnotationSerializationExclusionStrategyTest extends TestCase
|
|||||||
public void testNeverSkipClasses() throws Exception {
|
public void testNeverSkipClasses() throws Exception {
|
||||||
assertFalse(strategy.shouldSkipClass(MockObject.class));
|
assertFalse(strategy.shouldSkipClass(MockObject.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSkipNonAnnotatedFields() throws Exception {
|
public void testSkipNonAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("hiddenField");
|
Field f = MockObject.class.getField("hiddenField");
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSkipExplicitlySkippedFields() throws Exception {
|
public void testSkipExplicitlySkippedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("explicitlyHiddenField");
|
Field f = MockObject.class.getField("explicitlyHiddenField");
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNeverSkipExposedAnnotatedFields() throws Exception {
|
public void testNeverSkipExposedAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("exposedField");
|
Field f = MockObject.class.getField("exposedField");
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception {
|
public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception {
|
||||||
Field f = MockObject.class.getField("explicitlyExposedField");
|
Field f = MockObject.class.getField("explicitlyExposedField");
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@ -67,7 +67,7 @@ public class ExposeAnnotationSerializationExclusionStrategyTest extends TestCase
|
|||||||
|
|
||||||
@Expose(serialize=true)
|
@Expose(serialize=true)
|
||||||
public final int explicitlyExposedField = 0;
|
public final int explicitlyExposedField = 0;
|
||||||
|
|
||||||
@Expose(serialize=false)
|
@Expose(serialize=false)
|
||||||
public final int explicitlyHiddenField = 0;
|
public final int explicitlyHiddenField = 0;
|
||||||
|
|
||||||
|
77
gson/src/test/java/com/google/gson/FieldAttributesTest.java
Normal file
77
gson/src/test/java/com/google/gson/FieldAttributesTest.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 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;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the {@link FieldAttributes} class.
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
* @author Joel Leitch
|
||||||
|
*/
|
||||||
|
public class FieldAttributesTest extends TestCase {
|
||||||
|
private FieldAttributes fieldAttributes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
fieldAttributes = new FieldAttributes(Foo.class.getField("bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNullField() throws Exception {
|
||||||
|
try {
|
||||||
|
new FieldAttributes(null);
|
||||||
|
fail("Field parameter can not be null");
|
||||||
|
} catch (IllegalArgumentException expected) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testModifiers() throws Exception {
|
||||||
|
assertFalse(fieldAttributes.hasModifier(Modifier.STATIC));
|
||||||
|
assertFalse(fieldAttributes.hasModifier(Modifier.FINAL));
|
||||||
|
assertFalse(fieldAttributes.hasModifier(Modifier.ABSTRACT));
|
||||||
|
assertFalse(fieldAttributes.hasModifier(Modifier.VOLATILE));
|
||||||
|
assertFalse(fieldAttributes.hasModifier(Modifier.PROTECTED));
|
||||||
|
|
||||||
|
assertTrue(fieldAttributes.hasModifier(Modifier.PUBLIC));
|
||||||
|
assertTrue(fieldAttributes.hasModifier(Modifier.TRANSIENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsSynthetic() throws Exception {
|
||||||
|
assertFalse(fieldAttributes.isSynthetic());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testName() throws Exception {
|
||||||
|
assertEquals("bar", fieldAttributes.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeclaredTypeAndClass() throws Exception {
|
||||||
|
Type expectedType = new TypeToken<List<String>>() {}.getType();
|
||||||
|
assertEquals(expectedType, fieldAttributes.getDeclaredType());
|
||||||
|
assertEquals(List.class, fieldAttributes.getDeclaredClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Foo {
|
||||||
|
public transient List<String> bar;
|
||||||
|
}
|
||||||
|
}
|
@ -16,11 +16,13 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.common.TestTypes.ClassWithNoFields;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
import com.google.gson.common.TestTypes;
|
||||||
|
import com.google.gson.common.TestTypes.ClassWithNoFields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functional tests for Gson that depend on some internal package-protected elements of
|
* Functional tests for Gson that depend on some internal package-protected elements of
|
||||||
@ -32,11 +34,45 @@ import java.lang.reflect.Modifier;
|
|||||||
*/
|
*/
|
||||||
public class FunctionWithInternalDependenciesTest extends TestCase {
|
public class FunctionWithInternalDependenciesTest extends TestCase {
|
||||||
|
|
||||||
public void testAnonymousLocalClassesSerialization() {
|
public void testAnonymousLocalClassesSerialization() throws Exception {
|
||||||
Gson gson = new Gson(new ModifierBasedExclusionStrategy(
|
LinkedList<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||||
true, Modifier.TRANSIENT, Modifier.STATIC), Gson.DEFAULT_NAMING_POLICY);
|
strategies.add(new SyntheticFieldExclusionStrategy(true));
|
||||||
|
strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC));
|
||||||
|
ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
|
||||||
|
Gson gson = new Gson(exclusionStrategy, exclusionStrategy, Gson.DEFAULT_NAMING_POLICY,
|
||||||
|
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
|
||||||
|
Gson.DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(),
|
||||||
|
DefaultTypeAdapters.getDefaultDeserializers(), Gson.DEFAULT_JSON_NON_EXECUTABLE);
|
||||||
assertEquals("{}", gson.toJson(new ClassWithNoFields() {
|
assertEquals("{}", gson.toJson(new ClassWithNoFields() {
|
||||||
// empty anonymous class
|
// empty anonymous class
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(Joel): Move this to some other functional test once exclusion policies are
|
||||||
|
// available to the public
|
||||||
|
public void testUserDefinedExclusionPolicies() throws Exception {
|
||||||
|
Gson gson = new GsonBuilder()
|
||||||
|
.setExclusionStrategies(new UserDefinedExclusionStrategy(String.class))
|
||||||
|
.create();
|
||||||
|
|
||||||
|
String json = gson.toJson(new TestTypes.StringWrapper("someValue"));
|
||||||
|
assertEquals("{}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UserDefinedExclusionStrategy implements ExclusionStrategy {
|
||||||
|
private final Class<?> excludedThisClass;
|
||||||
|
|
||||||
|
UserDefinedExclusionStrategy(Class<?> excludedThisClass) {
|
||||||
|
this.excludedThisClass = excludedThisClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
return excludedThisClass.equals(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
return excludedThisClass.equals(f.getDeclaredClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public class InnerClassExclusionStrategyTest extends TestCase {
|
|||||||
public StaticNestedClass staticNestedClass;
|
public StaticNestedClass staticNestedClass;
|
||||||
|
|
||||||
private InnerClassExclusionStrategy strategy;
|
private InnerClassExclusionStrategy strategy;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
@ -43,25 +43,25 @@ public class InnerClassExclusionStrategyTest extends TestCase {
|
|||||||
Class<?> clazz = innerClass.getClass();
|
Class<?> clazz = innerClass.getClass();
|
||||||
assertTrue(strategy.shouldSkipClass(clazz));
|
assertTrue(strategy.shouldSkipClass(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testExcludeInnerClassField() throws Exception {
|
public void testExcludeInnerClassField() throws Exception {
|
||||||
Field f = getClass().getField("innerClass");
|
Field f = getClass().getField("innerClass");
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIncludeStaticNestedClassObject() throws Exception {
|
public void testIncludeStaticNestedClassObject() throws Exception {
|
||||||
Class<?> clazz = staticNestedClass.getClass();
|
Class<?> clazz = staticNestedClass.getClass();
|
||||||
assertFalse(strategy.shouldSkipClass(clazz));
|
assertFalse(strategy.shouldSkipClass(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIncludeStaticNestedClassField() throws Exception {
|
public void testIncludeStaticNestedClassField() throws Exception {
|
||||||
Field f = getClass().getField("staticNestedClass");
|
Field f = getClass().getField("staticNestedClass");
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
class InnerClass {
|
class InnerClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class StaticNestedClass {
|
static class StaticNestedClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,10 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.ExclusionStrategy;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a configurable {@link ExclusionStrategy} that can be used for
|
* This is a configurable {@link ExclusionStrategy} that can be used for
|
||||||
* unit testing.
|
* unit testing.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@ -35,7 +32,7 @@ public class MockExclusionStrategy implements ExclusionStrategy {
|
|||||||
this.skipField = skipField;
|
this.skipField = skipField;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldSkipField(Field f) {
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
return skipField;
|
return skipField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.NullExclusionStrategy;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +37,7 @@ public class NullExclusionStrategyTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testNeverSkipsField() throws Exception {
|
public void testNeverSkipsField() throws Exception {
|
||||||
assertFalse(strategy.shouldSkipField("".getClass().getFields()[0]));
|
assertFalse(strategy.shouldSkipField(
|
||||||
|
new FieldAttributes("".getClass().getFields()[0])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.annotations.Since;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import com.google.gson.annotations.Since;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the {@link VersionExclusionStrategy} class.
|
* Unit tests for the {@link VersionExclusionStrategy} class.
|
||||||
@ -41,27 +41,27 @@ public class VersionExclusionStrategyTest extends TestCase {
|
|||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
Field f = clazz.getField("someField");
|
Field f = clazz.getField("someField");
|
||||||
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION);
|
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION);
|
||||||
|
|
||||||
assertFalse(strategy.shouldSkipClass(clazz));
|
assertFalse(strategy.shouldSkipClass(clazz));
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClassAndFieldAreBehindInVersion() throws Exception {
|
public void testClassAndFieldAreBehindInVersion() throws Exception {
|
||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
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));
|
||||||
assertFalse(strategy.shouldSkipField(f));
|
assertFalse(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClassAndFieldAreAheadInVersion() throws Exception {
|
public void testClassAndFieldAreAheadInVersion() throws Exception {
|
||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
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));
|
||||||
assertTrue(strategy.shouldSkipField(f));
|
assertTrue(strategy.shouldSkipField(new FieldAttributes(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Since(VERSION)
|
@Since(VERSION)
|
||||||
|
Loading…
Reference in New Issue
Block a user