Provide a means to add serialization or deserialization specific exclusion strategies.

This commit is contained in:
Joel Leitch 2011-02-04 03:09:41 +00:00
parent ea48a1debf
commit 114633fbf9
26 changed files with 201 additions and 464 deletions

View File

@ -21,13 +21,13 @@ package com.google.gson;
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy2 { final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return isAnonymousOrLocal(f.getDeclaredClass()); return isAnonymousOrLocal(f.getDeclaredClass());
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return isAnonymousOrLocal(clazz); return isAnonymousOrLocal(clazz);
} }

View File

@ -19,31 +19,31 @@ package com.google.gson;
import java.util.Collection; import java.util.Collection;
/** /**
* A wrapper class used to collect numerous {@link ExclusionStrategy2} objects * A wrapper class used to collect numerous {@link ExclusionStrategy} objects
* and perform a short-circuited OR operation. * and perform a short-circuited OR operation.
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
final class DisjunctionExclusionStrategy implements ExclusionStrategy2 { final class DisjunctionExclusionStrategy implements ExclusionStrategy {
private final Collection<ExclusionStrategy2> strategies; private final Collection<ExclusionStrategy> strategies;
public DisjunctionExclusionStrategy(Collection<ExclusionStrategy2> strategies) { public DisjunctionExclusionStrategy(Collection<ExclusionStrategy> strategies) {
Preconditions.checkNotNull(strategies); Preconditions.checkNotNull(strategies);
this.strategies = strategies; this.strategies = strategies;
} }
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
for (ExclusionStrategy2 strategy : strategies) { for (ExclusionStrategy strategy : strategies) {
if (strategy.shouldSkipField(f, mode)) { if (strategy.shouldSkipField(f)) {
return true; return true;
} }
} }
return false; return false;
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
for (ExclusionStrategy2 strategy : strategies) { for (ExclusionStrategy strategy : strategies) {
if (strategy.shouldSkipClass(clazz, mode)) { if (strategy.shouldSkipClass(clazz)) {
return true; return true;
} }
} }

View File

@ -71,6 +71,10 @@ package com.google.gson;
* .setExclusionStrategies(excludeStrings) * .setExclusionStrategies(excludeStrings)
* .create(); * .create();
* </pre> * </pre>
*
* <p>For certain model classes, you may only want to serialize a field, but exclude it for
* deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
* however, you would register it with the
* *
* @author Inderjeet Singh * @author Inderjeet Singh
* @author Joel Leitch * @author Joel Leitch
@ -78,9 +82,7 @@ package com.google.gson;
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...) * @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
* *
* @since 1.4 * @since 1.4
* @deprecated use the more powerful {@link ExclusionStrategy2} instead.
*/ */
@Deprecated
public interface ExclusionStrategy { public interface ExclusionStrategy {
/** /**

View File

@ -1,125 +0,0 @@
/*
* Copyright (C) 2011 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 strategy (or policy) definition that is used to decide whether or not a field or top-level
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
* if the {@link #shouldSkipClass(Class, Mode)} method returns false then that class or field
* type will not be part of the JSON output. For deserialization, if
* {@link #shouldSkipClass(Class, , Context)} returns false, then it will not be set as part of
* the Java object structure.
*
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
*
* <p><strong>Exclude fields and objects based on a particular class type for both serialization
* and deserialization:</strong>
* <pre class="code">
* public class SpecificClassExclusionStrategy implements ExclusionStrategy2 {
* private final Class&lt;?&gt; excludedThisClass;
*
* public SpecificClassExclusionStrategy(Class&lt;?&gt; excludedThisClass) {
* this.excludedThisClass = excludedThisClass;
* }
*
* public boolean shouldSkipClass(Class&lt;?&gt; clazz, Context context) {
* return excludedThisClass.equals(clazz);
* }
*
* public boolean shouldSkipField(FieldAttributes f, Context context) {
* return excludedThisClass.equals(f.getDeclaredClass());
* }
* }
* </pre>
*
* <p><strong>Excludes fields and objects based on a particular annotation for both serialization
* and deserialization:</strong>
* <pre class="code">
* public &#64interface FooAnnotation {
* // some implementation here
* }
*
* // Excludes any field (or class) that is tagged with an "&#64FooAnnotation"
* public class FooAnnotationExclusionStrategy implements ExclusionStrategy2 {
* public boolean shouldSkipClass(Class&lt;?&gt; clazz, Context context) {
* return clazz.getAnnotation(FooAnnotation.class) != null;
* }
*
* public boolean shouldSkipField(FieldAttributes f, Context context) {
* return f.getAnnotation(FooAnnotation.class) != null;
* }
* }
* </pre>
*
* <p><strong>Exclude fields and objects based on a particular class type for serialization
* only:</strong>
* <pre class="code">
* public class SpecificClassExclusionStrategy implements ExclusionStrategy2 {
* private final Class&lt;?&gt; excludedThisClass;
*
* public SpecificClassExclusionStrategy(Class&lt;?&gt; excludedThisClass) {
* this.excludedThisClass = excludedThisClass;
* }
*
* public boolean shouldSkipClass(Class&lt;?&gt; clazz, Context context) {
* if (context == Context.SERIALIZE) {
* return excludedThisClass.equals(clazz);
* } else {
* return false;
* }
* }
*
* public boolean shouldSkipField(FieldAttributes f, Context context) {
* if (context == Context.SERIALIZE) {
* return excludedThisClass.equals(f.getDeclaredClass());
* } else {
* return false;
* }
* }
* }
* </pre>
*
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
* the {@code GsonBuilder} is required. The following is an example of how you can use the
* {@code GsonBuilder} to configure Gson to use one of the above sample:
* <pre class="code">
* ExclusionStrategy2 excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
* .setExclusionStrategies(excludeStrings)
* .create();
* </pre>
*
* @author Joel Leitch
*
* @since 1.7
*/
public interface ExclusionStrategy2 {
/**
* @param f the field object that is under test
* @param mode the current mode the Gson is running in
* @return true if the field should be ignored; otherwise false
*/
public boolean shouldSkipField(FieldAttributes f, Mode mode);
/**
* @param clazz the class object that is under test
* @param mode the current mode the Gson is running in
* @return true if the class should be ignored; otherwise false
*/
public boolean shouldSkipClass(Class<?> clazz, Mode mode);
}

View File

@ -23,23 +23,16 @@ import com.google.gson.annotations.Expose;
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
public class ExposeAnnotationExclusionStrategy implements ExclusionStrategy2 { public class ExposeAnnotationDeserializationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return false; return false;
} }
public boolean shouldSkipField(FieldAttributes f, Mode mode) { 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;
} }
return !annotation.deserialize();
if (mode == Mode.SERIALIZE) {
return !annotation.serialize();
} else if (mode == Mode.DESERIALIZE) {
return !annotation.deserialize();
}
return false;
} }
} }

View File

@ -16,24 +16,23 @@
package com.google.gson; package com.google.gson;
import com.google.gson.annotations.Expose;
/** /**
* Adapts the old {@link ExclusionStrategy} into the newer {@link ExclusionStrategy2} type. * Excludes fields that do not have the {@link Expose} annotation
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
class ExclusionStrategy2Adapter implements ExclusionStrategy2 { public class ExposeAnnotationSerializationExclusionStrategy implements ExclusionStrategy {
private final ExclusionStrategy strategy; public boolean shouldSkipClass(Class<?> clazz) {
return false;
public ExclusionStrategy2Adapter(ExclusionStrategy strategy) {
Preconditions.checkNotNull(strategy);
this.strategy = strategy;
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return strategy.shouldSkipClass(clazz); Expose annotation = f.getAnnotation(Expose.class);
} if (annotation == null) {
return true;
public boolean shouldSkipField(FieldAttributes f, Mode mode) { }
return strategy.shouldSkipField(f); return !annotation.serialize();
} }
} }

View File

@ -90,11 +90,12 @@ public final class Gson {
static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY = static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY =
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy()); new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
private static final ExclusionStrategy2 DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy(); private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy();
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
private final ExclusionStrategy2 exclusionStrategy; private final ExclusionStrategy deserializationExclusionStrategy;
private final ExclusionStrategy serializationExclusionStrategy;
private final FieldNamingStrategy2 fieldNamingPolicy; private final FieldNamingStrategy2 fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor; private final MappedObjectConstructor objectConstructor;
@ -144,18 +145,20 @@ public final class Gson {
* </ul> * </ul>
*/ */
public Gson() { public Gson() {
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY, this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
false, DefaultTypeAdapters.getAllDefaultSerializers(), false, DefaultTypeAdapters.getAllDefaultSerializers(),
DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false); DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
} }
Gson(ExclusionStrategy2 exclusionStrategy, FieldNamingStrategy2 fieldNamingPolicy, Gson(ExclusionStrategy deserializationExclusionStrategy,
ExclusionStrategy serializationExclusionStrategy, FieldNamingStrategy2 fieldNamingPolicy,
MappedObjectConstructor objectConstructor, boolean serializeNulls, MappedObjectConstructor objectConstructor, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers, ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers, ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) { boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) {
this.exclusionStrategy = exclusionStrategy; this.deserializationExclusionStrategy = deserializationExclusionStrategy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.fieldNamingPolicy = fieldNamingPolicy; this.fieldNamingPolicy = fieldNamingPolicy;
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
this.serializeNulls = serializeNulls; this.serializeNulls = serializeNulls;
@ -166,12 +169,12 @@ public final class Gson {
this.prettyPrinting = prettyPrinting; this.prettyPrinting = prettyPrinting;
} }
private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy2 strategy) { private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy strategy) {
return new ObjectNavigatorFactory(strategy, fieldNamingPolicy); return new ObjectNavigatorFactory(strategy, fieldNamingPolicy);
} }
private static ExclusionStrategy2 createExclusionStrategy() { private static ExclusionStrategy createExclusionStrategy() {
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>(); List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY); strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY); strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY); strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
@ -219,7 +222,7 @@ public final class Gson {
return JsonNull.createJsonNull(); return JsonNull.createJsonNull();
} }
JsonSerializationContextDefault context = new JsonSerializationContextDefault( JsonSerializationContextDefault context = new JsonSerializationContextDefault(
createDefaultObjectNavigatorFactory(exclusionStrategy), serializeNulls, serializers); createDefaultObjectNavigatorFactory(serializationExclusionStrategy), serializeNulls, serializers);
return context.serialize(src, typeOfSrc, true); return context.serialize(src, typeOfSrc, true);
} }
@ -549,8 +552,8 @@ public final class Gson {
return null; return null;
} }
JsonDeserializationContext context = new JsonDeserializationContextDefault( JsonDeserializationContext context = new JsonDeserializationContextDefault(
createDefaultObjectNavigatorFactory(exclusionStrategy), deserializers, createDefaultObjectNavigatorFactory(deserializationExclusionStrategy),
objectConstructor); deserializers, objectConstructor);
T target = (T) context.deserialize(json, typeOfT); T target = (T) context.deserialize(json, typeOfT);
return target; return target;
} }

View File

@ -18,11 +18,12 @@ 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.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter; import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
@ -54,11 +55,17 @@ import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
public final class GsonBuilder { public final class GsonBuilder {
private static final InnerClassExclusionStrategy innerClassExclusionStrategy = private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
new InnerClassExclusionStrategy(); new InnerClassExclusionStrategy();
private static final ExposeAnnotationExclusionStrategy exposeAnnotationExclusionStrategy = private static final ExposeAnnotationDeserializationExclusionStrategy
new ExposeAnnotationExclusionStrategy(); exposeAnnotationDeserializationExclusionStrategy =
new ExposeAnnotationDeserializationExclusionStrategy();
private static final ExposeAnnotationSerializationExclusionStrategy
exposeAnnotationSerializationExclusionStrategy =
new ExposeAnnotationSerializationExclusionStrategy();
private final Collection<ExclusionStrategy2> exclusionStrategies = private final Set<ExclusionStrategy> serializeExclusionStrategies =
new HashSet<ExclusionStrategy2>(); new HashSet<ExclusionStrategy>();
private final Set<ExclusionStrategy> deserializeExclusionStrategies =
new HashSet<ExclusionStrategy>();
private double ignoreVersionsAfter; private double ignoreVersionsAfter;
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy; private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
@ -86,8 +93,10 @@ public final class GsonBuilder {
*/ */
public GsonBuilder() { public GsonBuilder() {
// add default exclusion strategies // add default exclusion strategies
exclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY); deserializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
exclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY); deserializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
serializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
serializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
// setup default values // setup default values
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS; ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
@ -248,32 +257,32 @@ public final class GsonBuilder {
* @param strategies the set of strategy object to apply during object (de)serialization. * @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 * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4 * @since 1.4
* @deprecated convert your {@code strategies} to {@link ExclusionStrategy2} and use the
* {@link #setExclusionStrategies(ExclusionStrategy2...) method instead.
*/ */
@Deprecated
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) { public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
for (ExclusionStrategy strategy : strategies) { List<ExclusionStrategy> strategyList = Arrays.asList(strategies);
exclusionStrategies.add(new ExclusionStrategy2Adapter(strategy)); serializeExclusionStrategies.addAll(strategyList);
} deserializeExclusionStrategies.addAll(strategyList);
return this; return this;
} }
/** /**
* Configures Gson to apply a set of exclusion strategies during both serialization and * Configures Gson to apply a set of exclusion strategies during either serialization or
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule. * deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
* This means that if one of the {@code strategies} suggests that a field (or class) should be * This means that if one of the {@code strategies} suggests that a field (or class) should be
* skipped in the current mode then that field (or object) is skipped during the particular Gson * skipped then that field (or object) is skipped during either serialization or deserialization
* mode. * depending on the {@code mode} that is passed into this method.
* *
* @param strategies the set of strategy object to apply during object (de)serialization. * @param strategies the set of strategy object to apply during the {@code mode}.
* @param the mode of Gson (either serialization or deserialization) as to when the
* {@code strategies} should be applied.
* @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.7 * @since 1.7
*/ */
public GsonBuilder setExclusionStrategies(ExclusionStrategy2... strategies) { public GsonBuilder setExclusionStrategies(Mode mode, ExclusionStrategy... strategies) {
for (ExclusionStrategy2 strategy : strategies) { Preconditions.checkNotNull(mode);
exclusionStrategies.add(strategy); Set<ExclusionStrategy> strategySet = (mode == Mode.SERIALIZE)
} ? serializeExclusionStrategies : deserializeExclusionStrategies;
strategySet.addAll(Arrays.asList(strategies));
return this; return this;
} }
@ -519,20 +528,27 @@ 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<ExclusionStrategy2> strategies = List<ExclusionStrategy> deserializationStrategies =
new LinkedList<ExclusionStrategy2>(exclusionStrategies); new LinkedList<ExclusionStrategy>(deserializeExclusionStrategies);
strategies.add(modifierBasedExclusionStrategy); List<ExclusionStrategy> serializationStrategies =
new LinkedList<ExclusionStrategy>(serializeExclusionStrategies);
deserializationStrategies.add(modifierBasedExclusionStrategy);
serializationStrategies.add(modifierBasedExclusionStrategy);
if (!serializeInnerClasses) { if (!serializeInnerClasses) {
strategies.add(innerClassExclusionStrategy); deserializationStrategies.add(innerClassExclusionStrategy);
serializationStrategies.add(innerClassExclusionStrategy);
} }
if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) { if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) {
strategies.add(new VersionExclusionStrategy(ignoreVersionsAfter)); VersionExclusionStrategy versionExclusionStrategy =
new VersionExclusionStrategy(ignoreVersionsAfter);
deserializationStrategies.add(versionExclusionStrategy);
serializationStrategies.add(versionExclusionStrategy);
} }
if (excludeFieldsWithoutExposeAnnotation) { if (excludeFieldsWithoutExposeAnnotation) {
strategies.add(exposeAnnotationExclusionStrategy); deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
} }
ExclusionStrategy2 exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers = ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf(); DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf();
@ -558,7 +574,9 @@ public final class GsonBuilder {
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators); MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor, serializeNulls, Gson gson = new Gson(new DisjunctionExclusionStrategy(deserializationStrategies),
new DisjunctionExclusionStrategy(serializationStrategies),
fieldNamingPolicy, objConstructor, serializeNulls,
customSerializers, customDeserializers, generateNonExecutableJson, escapeHtmlChars, customSerializers, customDeserializers, generateNonExecutableJson, escapeHtmlChars,
prettyPrinting); prettyPrinting);
return gson; return gson;

View File

@ -23,13 +23,13 @@ import java.lang.reflect.Modifier;
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
class InnerClassExclusionStrategy implements ExclusionStrategy2 { class InnerClassExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return isInnerClass(f.getDeclaredClass()); return isInnerClass(f.getDeclaredClass());
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return isInnerClass(clazz); return isInnerClass(clazz);
} }

View File

@ -58,10 +58,6 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
} }
return target; return target;
} }
public Mode getMode() {
return Mode.DESERIALIZE;
}
protected abstract T constructTarget(); protected abstract T constructTarget();

View File

@ -47,10 +47,6 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
public Object getTarget() { public Object getTarget() {
return null; return null;
} }
public Mode getMode() {
return Mode.SERIALIZE;
}
public void start(ObjectTypePair node) { public void start(ObjectTypePair node) {
if (node == null) { if (node == null) {

View File

@ -26,7 +26,7 @@ import java.util.HashSet;
* @author Inderjeet Singh * @author Inderjeet Singh
* @author Joel Leitch * @author Joel Leitch
*/ */
final class ModifierBasedExclusionStrategy implements ExclusionStrategy2 { final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
private final Collection<Integer> modifiers; private final Collection<Integer> modifiers;
public ModifierBasedExclusionStrategy(int... modifiers) { public ModifierBasedExclusionStrategy(int... modifiers) {
@ -38,7 +38,7 @@ final class ModifierBasedExclusionStrategy implements ExclusionStrategy2 {
} }
} }
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
for (int modifier : modifiers) { for (int modifier : modifiers) {
if (f.hasModifier(modifier)) { if (f.hasModifier(modifier)) {
return true; return true;
@ -47,7 +47,7 @@ final class ModifierBasedExclusionStrategy implements ExclusionStrategy2 {
return false; return false;
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return false; return false;
} }
} }

View File

@ -24,13 +24,13 @@ package com.google.gson;
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
final class NullExclusionStrategy implements ExclusionStrategy2 { final class NullExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return false; return false;
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return false; return false;
} }
} }

View File

@ -75,11 +75,9 @@ final class ObjectNavigator {
* Retrieve the current target * Retrieve the current target
*/ */
Object getTarget(); Object getTarget();
Mode getMode();
} }
private final ExclusionStrategy2 exclusionStrategy; private final ExclusionStrategy exclusionStrategy;
private final ObjectTypePair objTypePair; private final ObjectTypePair objTypePair;
/** /**
@ -89,7 +87,7 @@ final class ObjectNavigator {
* the concrete strategy object to be used to filter out fields of an * the concrete strategy object to be used to filter out fields of an
* object. * object.
*/ */
ObjectNavigator(ObjectTypePair objTypePair, ExclusionStrategy2 exclusionStrategy) { ObjectNavigator(ObjectTypePair objTypePair, ExclusionStrategy exclusionStrategy) {
Preconditions.checkNotNull(exclusionStrategy); Preconditions.checkNotNull(exclusionStrategy);
this.objTypePair = objTypePair; this.objTypePair = objTypePair;
@ -101,7 +99,7 @@ final class ObjectNavigator {
* does not get visited. * does not get visited.
*/ */
public void accept(Visitor visitor) { public void accept(Visitor visitor) {
if (exclusionStrategy.shouldSkipClass(Types.getRawType(objTypePair.type), visitor.getMode())) { if (exclusionStrategy.shouldSkipClass(Types.getRawType(objTypePair.type))) {
return; return;
} }
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair); boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
@ -145,13 +143,12 @@ final class ObjectNavigator {
} }
private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) { private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) {
Mode mode = visitor.getMode();
Field[] fields = clazz.getDeclaredFields(); Field[] fields = clazz.getDeclaredFields();
AccessibleObject.setAccessible(fields, true); AccessibleObject.setAccessible(fields, true);
for (Field f : fields) { for (Field f : fields) {
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
if (exclusionStrategy.shouldSkipField(fieldAttributes, mode) if (exclusionStrategy.shouldSkipField(fieldAttributes)
|| exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass(), mode)) { || exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
continue; // skip continue; // skip
} }
Type declaredTypeOfField = getTypeInfoForField(f, objTypePair.type); Type declaredTypeOfField = getTypeInfoForField(f, objTypePair.type);

View File

@ -24,7 +24,7 @@ package com.google.gson;
* @author Joel Leitch * @author Joel Leitch
*/ */
final class ObjectNavigatorFactory { final class ObjectNavigatorFactory {
private final ExclusionStrategy2 strategy; private final ExclusionStrategy strategy;
private final FieldNamingStrategy2 fieldNamingPolicy; private final FieldNamingStrategy2 fieldNamingPolicy;
/** /**
@ -36,7 +36,7 @@ final class ObjectNavigatorFactory {
* @param fieldNamingPolicy the naming policy that should be applied to field * @param fieldNamingPolicy the naming policy that should be applied to field
* names * names
*/ */
public ObjectNavigatorFactory(ExclusionStrategy2 strategy, FieldNamingStrategy2 fieldNamingPolicy) { public ObjectNavigatorFactory(ExclusionStrategy strategy, FieldNamingStrategy2 fieldNamingPolicy) {
Preconditions.checkNotNull(fieldNamingPolicy); Preconditions.checkNotNull(fieldNamingPolicy);
this.strategy = (strategy == null ? new NullExclusionStrategy() : strategy); this.strategy = (strategy == null ? new NullExclusionStrategy() : strategy);
this.fieldNamingPolicy = fieldNamingPolicy; this.fieldNamingPolicy = fieldNamingPolicy;

View File

@ -26,18 +26,18 @@ package com.google.gson;
* *
* @since 1.4 * @since 1.4
*/ */
class SyntheticFieldExclusionStrategy implements ExclusionStrategy2 { class SyntheticFieldExclusionStrategy implements ExclusionStrategy {
private final boolean skipSyntheticFields; private final boolean skipSyntheticFields;
SyntheticFieldExclusionStrategy(boolean skipSyntheticFields) { SyntheticFieldExclusionStrategy(boolean skipSyntheticFields) {
this.skipSyntheticFields = skipSyntheticFields; this.skipSyntheticFields = skipSyntheticFields;
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return false; return false;
} }
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return skipSyntheticFields && f.isSynthetic(); return skipSyntheticFields && f.isSynthetic();
} }

View File

@ -25,7 +25,7 @@ import com.google.gson.annotations.Until;
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
final class VersionExclusionStrategy implements ExclusionStrategy2 { final class VersionExclusionStrategy implements ExclusionStrategy {
private final double version; private final double version;
public VersionExclusionStrategy(double version) { public VersionExclusionStrategy(double version) {
@ -33,11 +33,11 @@ final class VersionExclusionStrategy implements ExclusionStrategy2 {
this.version = version; this.version = version;
} }
public boolean shouldSkipField(FieldAttributes f, Mode mode) { public boolean shouldSkipField(FieldAttributes f) {
return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class)); return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class));
} }
public boolean shouldSkipClass(Class<?> clazz, Mode mode) { public boolean shouldSkipClass(Class<?> clazz) {
return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class)); return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class));
} }

View File

@ -16,11 +16,11 @@
package com.google.gson; package com.google.gson;
import junit.framework.TestCase;
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.
* *
@ -28,38 +28,38 @@ import junit.framework.TestCase;
*/ */
public class DisjunctionExclusionStrategyTest extends TestCase { public class DisjunctionExclusionStrategyTest extends TestCase {
private static final ExclusionStrategy2 FALSE_STRATEGY = private static final ExclusionStrategy FALSE_STRATEGY =
new MockExclusionStrategy2(false, false, null); new MockExclusionStrategy(false, false);
private static final ExclusionStrategy2 TRUE_STRATEGY = private static final ExclusionStrategy TRUE_STRATEGY =
new MockExclusionStrategy2(true, true, null); new MockExclusionStrategy(true, true);
private static final Class<?> CLAZZ = String.class; private static final Class<?> CLAZZ = String.class;
private static final FieldAttributes FIELD = new FieldAttributes(CLAZZ, CLAZZ.getFields()[0]); private static final FieldAttributes FIELD = new FieldAttributes(CLAZZ, CLAZZ.getFields()[0]);
public void testBadInstantiation() throws Exception { public void testBadInstantiation() throws Exception {
try { try {
List<ExclusionStrategy2> constructorParam = null; List<ExclusionStrategy> constructorParam = null;
new DisjunctionExclusionStrategy(constructorParam); new DisjunctionExclusionStrategy(constructorParam);
fail("Should throw an exception"); fail("Should throw an exception");
} catch (IllegalArgumentException expected) { } } catch (IllegalArgumentException expected) { }
} }
public void testSkipFieldsWithMixedTrueAndFalse() throws Exception { public void testSkipFieldsWithMixedTrueAndFalse() throws Exception {
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>(); List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
strategies.add(FALSE_STRATEGY); strategies.add(FALSE_STRATEGY);
strategies.add(TRUE_STRATEGY); strategies.add(TRUE_STRATEGY);
DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies);
assertTrue(strategy.shouldSkipClass(CLAZZ, Mode.SERIALIZE)); assertTrue(strategy.shouldSkipClass(CLAZZ));
assertTrue(strategy.shouldSkipField(FIELD, Mode.SERIALIZE)); assertTrue(strategy.shouldSkipField(FIELD));
} }
public void testSkipFieldsWithFalseOnly() throws Exception { public void testSkipFieldsWithFalseOnly() throws Exception {
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>(); List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
strategies.add(FALSE_STRATEGY); strategies.add(FALSE_STRATEGY);
DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies);
assertFalse(strategy.shouldSkipClass(CLAZZ, Mode.SERIALIZE)); assertFalse(strategy.shouldSkipClass(CLAZZ));
assertFalse(strategy.shouldSkipField(FIELD, Mode.SERIALIZE)); assertFalse(strategy.shouldSkipField(FIELD));
} }
} }

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) 2011 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.Field;
import junit.framework.TestCase;
/**
* Unit test for the {@link ExclusionStrategy2Adapter} class.
*
* @author Joel Leitch
*/
public class ExclusionStrategy2AdapterTest extends TestCase {
public void testConstruction() throws Exception {
try {
new ExclusionStrategy2Adapter(null);
fail();
} catch (IllegalArgumentException expected) {}
}
public void testAdapterDoesSameForBothModes() throws Exception {
ExclusionStrategy2Adapter adapter =
new ExclusionStrategy2Adapter(new MockExclusionStrategy(true, false));
assertTrue(adapter.shouldSkipClass(String.class, Mode.DESERIALIZE));
assertTrue(adapter.shouldSkipClass(String.class, Mode.SERIALIZE));
Field f = String.class.getFields()[0];
assertFalse(adapter.shouldSkipField(new FieldAttributes(String.class, f), Mode.DESERIALIZE));
assertFalse(adapter.shouldSkipField(new FieldAttributes(String.class, f), Mode.SERIALIZE));
}
}

View File

@ -16,59 +16,61 @@
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;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.lang.reflect.Field;
/** /**
* Unit tests for the {@link ExposeAnnotationExclusionStrategy} class. * Unit tests for the {@link ExposeAnnotationSerializationExclusionStrategy} class.
* *
* @author Joel Leitch * @author Joel Leitch
*/ */
public class ExposeAnnotationExclusionStrategyTest extends TestCase { public class ExposeAnnotationExclusionStrategyTest extends TestCase {
private ExposeAnnotationExclusionStrategy strategy; private ExposeAnnotationDeserializationExclusionStrategy deserializationStrategy;
private ExposeAnnotationSerializationExclusionStrategy serializationStrategy;
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
strategy = new ExposeAnnotationExclusionStrategy(); deserializationStrategy = new ExposeAnnotationDeserializationExclusionStrategy();
serializationStrategy = new ExposeAnnotationSerializationExclusionStrategy();
} }
public void testNeverSkipClasses() throws Exception { public void testNeverSkipClasses() throws Exception {
assertFalse(strategy.shouldSkipClass(MockObject.class, Mode.DESERIALIZE)); assertFalse(deserializationStrategy.shouldSkipClass(MockObject.class));
assertFalse(strategy.shouldSkipClass(MockObject.class, Mode.SERIALIZE)); assertFalse(serializationStrategy.shouldSkipClass(MockObject.class));
} }
public void testSkipNonAnnotatedFields() throws Exception { public void testSkipNonAnnotatedFields() throws Exception {
FieldAttributes f = createFieldAttributes("hiddenField"); FieldAttributes f = createFieldAttributes("hiddenField");
assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); assertTrue(deserializationStrategy.shouldSkipField(f));
assertTrue(strategy.shouldSkipField(f, Mode.SERIALIZE)); assertTrue(serializationStrategy.shouldSkipField(f));
} }
public void testSkipExplicitlySkippedFields() throws Exception { public void testSkipExplicitlySkippedFields() throws Exception {
FieldAttributes f = createFieldAttributes("explicitlyHiddenField"); FieldAttributes f = createFieldAttributes("explicitlyHiddenField");
assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); assertTrue(deserializationStrategy.shouldSkipField(f));
assertTrue(strategy.shouldSkipField(f, Mode.SERIALIZE)); assertTrue(serializationStrategy.shouldSkipField(f));
} }
public void testNeverSkipExposedAnnotatedFields() throws Exception { public void testNeverSkipExposedAnnotatedFields() throws Exception {
FieldAttributes f = createFieldAttributes("exposedField"); FieldAttributes f = createFieldAttributes("exposedField");
assertFalse(strategy.shouldSkipField(f, Mode.DESERIALIZE)); assertFalse(deserializationStrategy.shouldSkipField(f));
assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); assertFalse(serializationStrategy.shouldSkipField(f));
} }
public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception { public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception {
FieldAttributes f = createFieldAttributes("explicitlyExposedField"); FieldAttributes f = createFieldAttributes("explicitlyExposedField");
assertFalse(strategy.shouldSkipField(f, Mode.DESERIALIZE)); assertFalse(deserializationStrategy.shouldSkipField(f));
assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); assertFalse(serializationStrategy.shouldSkipField(f));
} }
public void testDifferentSerializeAndDeserializeField() throws Exception { public void testDifferentSerializeAndDeserializeField() throws Exception {
FieldAttributes f = createFieldAttributes("explicitlyDifferentModeField"); FieldAttributes f = createFieldAttributes("explicitlyDifferentModeField");
assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); assertTrue(deserializationStrategy.shouldSkipField(f));
assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); assertFalse(serializationStrategy.shouldSkipField(f));
} }
private static FieldAttributes createFieldAttributes(String fieldName) throws Exception { private static FieldAttributes createFieldAttributes(String fieldName) throws Exception {

View File

@ -35,11 +35,11 @@ import com.google.gson.common.TestTypes.ClassWithNoFields;
public class FunctionWithInternalDependenciesTest extends TestCase { public class FunctionWithInternalDependenciesTest extends TestCase {
public void testAnonymousLocalClassesSerialization() throws Exception { public void testAnonymousLocalClassesSerialization() throws Exception {
LinkedList<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>(); LinkedList<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
strategies.add(new SyntheticFieldExclusionStrategy(true)); strategies.add(new SyntheticFieldExclusionStrategy(true));
strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC)); strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC));
ExclusionStrategy2 exclusionStrategy = new DisjunctionExclusionStrategy(strategies); ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
Gson gson = new Gson(exclusionStrategy, Gson.DEFAULT_NAMING_POLICY, Gson gson = new Gson(exclusionStrategy, exclusionStrategy, Gson.DEFAULT_NAMING_POLICY,
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
false, DefaultTypeAdapters.getDefaultSerializers(), false, DefaultTypeAdapters.getDefaultSerializers(),
DefaultTypeAdapters.getDefaultDeserializers(), Gson.DEFAULT_JSON_NON_EXECUTABLE, true, DefaultTypeAdapters.getDefaultDeserializers(), Gson.DEFAULT_JSON_NON_EXECUTABLE, true,
@ -48,32 +48,4 @@ public class FunctionWithInternalDependenciesTest extends TestCase {
// 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 ExclusionStrategy2 {
private final Class<?> excludedThisClass;
UserDefinedExclusionStrategy(Class<?> excludedThisClass) {
this.excludedThisClass = excludedThisClass;
}
public boolean shouldSkipClass(Class<?> clazz, Mode mode) {
return excludedThisClass.equals(clazz);
}
public boolean shouldSkipField(FieldAttributes f, Mode mode) {
return excludedThisClass.equals(f.getDeclaredClass());
}
}
} }

View File

@ -16,10 +16,10 @@
package com.google.gson; package com.google.gson;
import java.lang.reflect.Field;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.lang.reflect.Field;
/** /**
* Unit test for the {@link InnerClassExclusionStrategy} class. * Unit test for the {@link InnerClassExclusionStrategy} class.
* *
@ -41,26 +41,22 @@ public class InnerClassExclusionStrategyTest extends TestCase {
public void testExcludeInnerClassObject() throws Exception { public void testExcludeInnerClassObject() throws Exception {
Class<?> clazz = innerClass.getClass(); Class<?> clazz = innerClass.getClass();
assertTrue(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); assertTrue(strategy.shouldSkipClass(clazz));
assertTrue(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE));
} }
public void testExcludeInnerClassField() throws Exception { public void testExcludeInnerClassField() throws Exception {
Field f = getClass().getField("innerClass"); Field f = getClass().getField("innerClass");
assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.SERIALIZE)); assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f)));
assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.DESERIALIZE));
} }
public void testIncludeStaticNestedClassObject() throws Exception { public void testIncludeStaticNestedClassObject() throws Exception {
Class<?> clazz = staticNestedClass.getClass(); Class<?> clazz = staticNestedClass.getClass();
assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); assertFalse(strategy.shouldSkipClass(clazz));
assertFalse(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE));
} }
public void testIncludeStaticNestedClassField() throws Exception { public void testIncludeStaticNestedClassField() throws Exception {
Field f = getClass().getField("staticNestedClass"); Field f = getClass().getField("staticNestedClass");
assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.SERIALIZE)); assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f)));
assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.DESERIALIZE));
} }
class InnerClass { class InnerClass {

View File

@ -1,49 +0,0 @@
/*
* 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;
/**
* This is a configurable {@link ExclusionStrategy2} that can be used for
* unit testing.
*
* @author Joel Leitch
*/
public class MockExclusionStrategy2 implements ExclusionStrategy2 {
private final MockExclusionStrategy strategy;
private final Mode mode;
public MockExclusionStrategy2(boolean skipClass, boolean skipField, Mode mode) {
this.strategy = new MockExclusionStrategy(skipClass, skipField);
this.mode = mode;
}
public boolean shouldSkipField(FieldAttributes f, Mode mode) {
if (this.mode == null || this.mode == mode) {
return strategy.shouldSkipField(f);
} else {
return false;
}
}
public boolean shouldSkipClass(Class<?> clazz, Mode mode) {
if (this.mode == null || this.mode == mode) {
return strategy.shouldSkipClass(clazz);
} else {
return false;
}
}
}

View File

@ -33,16 +33,11 @@ public class NullExclusionStrategyTest extends TestCase {
} }
public void testNeverSkipsClass() throws Exception { public void testNeverSkipsClass() throws Exception {
assertFalse(strategy.shouldSkipClass(String.class, Mode.SERIALIZE)); assertFalse(strategy.shouldSkipClass(String.class));
assertFalse(strategy.shouldSkipClass(String.class, Mode.DESERIALIZE));
} }
public void testNeverSkipsField() throws Exception { public void testNeverSkipsField() throws Exception {
assertFalse(strategy.shouldSkipField( assertFalse(strategy.shouldSkipField(
new FieldAttributes(String.class, String.class.getFields()[0]), new FieldAttributes(String.class, String.class.getFields()[0])));
Mode.SERIALIZE));
assertFalse(strategy.shouldSkipField(
new FieldAttributes(String.class, String.class.getFields()[0]),
Mode.DESERIALIZE));
} }
} }

View File

@ -41,39 +41,30 @@ 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, Mode.DESERIALIZE));
assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); assertFalse(strategy.shouldSkipField(fieldAttributes));
assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE));
} }
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, Mode.DESERIALIZE));
assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); assertFalse(strategy.shouldSkipField(fieldAttributes));
assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE));
} }
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, Mode.DESERIALIZE));
assertTrue(strategy.shouldSkipClass(clazz, Mode.SERIALIZE));
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
assertTrue(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); assertTrue(strategy.shouldSkipField(fieldAttributes));
assertTrue(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE));
} }
@Since(VERSION) @Since(VERSION)

View File

@ -17,14 +17,11 @@
package com.google.gson.functional; package com.google.gson.functional;
import com.google.gson.ExclusionStrategy; import com.google.gson.ExclusionStrategy;
import com.google.gson.ExclusionStrategy2;
import com.google.gson.FieldAttributes; import com.google.gson.FieldAttributes;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.MockExclusionStrategy;
import com.google.gson.MockExclusionStrategy2;
import com.google.gson.Mode; import com.google.gson.Mode;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -43,41 +40,23 @@ import java.lang.annotation.Target;
*/ */
public class ExclusionStrategyFunctionalTest extends TestCase { public class ExclusionStrategyFunctionalTest extends TestCase {
private SampleObjectForTest src; private SampleObjectForTest src;
private Gson gson;
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
gson = new GsonBuilder()
.setExclusionStrategies(new MyExclusionStrategy(String.class))
.serializeNulls()
.create();
src = new SampleObjectForTest(); src = new SampleObjectForTest();
} }
public void testExclusionStrategySerialization() throws Exception { public void testExclusionStrategySerialization() throws Exception {
Gson gson = createGson(new MyExclusionStrategy(String.class)); Gson gson = createGson(new MyExclusionStrategy(String.class), null);
String json = gson.toJson(src); String json = gson.toJson(src);
assertFalse(json.contains("\"stringField\"")); assertFalse(json.contains("\"stringField\""));
assertFalse(json.contains("\"annotatedField\"")); assertFalse(json.contains("\"annotatedField\""));
assertTrue(json.contains("\"longField\"")); assertTrue(json.contains("\"longField\""));
} }
public void testExclusionStrategy2Serialization() throws Exception {
Gson gson = createGson(new MockExclusionStrategy2(false, true, Mode.DESERIALIZE));
String json = gson.toJson(src);
assertTrue(json.contains("\"stringField\""));
assertTrue(json.contains("\"annotatedField\""));
assertTrue(json.contains("\"longField\""));
gson = createGson(new MockExclusionStrategy2(false, true, Mode.SERIALIZE));
json = gson.toJson(src);
assertFalse(json.contains("\"stringField\""));
assertFalse(json.contains("\"annotatedField\""));
assertFalse(json.contains("\"longField\""));
}
public void testExclusionStrategyDeserialization() throws Exception { public void testExclusionStrategyDeserialization() throws Exception {
Gson gson = createGson(new MyExclusionStrategy(String.class), null);
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.add("annotatedField", new JsonPrimitive(src.annotatedField + 5)); json.add("annotatedField", new JsonPrimitive(src.annotatedField + 5));
json.add("stringField", new JsonPrimitive(src.stringField + "blah,blah")); json.add("stringField", new JsonPrimitive(src.stringField + "blah,blah"));
@ -90,17 +69,34 @@ public class ExclusionStrategyFunctionalTest extends TestCase {
assertEquals(src.annotatedField, target.annotatedField); assertEquals(src.annotatedField, target.annotatedField);
assertEquals(src.stringField, target.stringField); assertEquals(src.stringField, target.stringField);
} }
private static Gson createGson(ExclusionStrategy exclusionStrategy) {
return new GsonBuilder()
.setExclusionStrategies(exclusionStrategy)
.serializeNulls()
.create();
}
private static Gson createGson(ExclusionStrategy2 exclusionStrategy) { public void testExclusionStrategyWithMode() throws Exception {
return new GsonBuilder() SampleObjectForTest testObj = new SampleObjectForTest(
.setExclusionStrategies(exclusionStrategy) src.annotatedField + 5, src.stringField + "blah,blah",
src.longField + 655L);
Gson gson = createGson(new MyExclusionStrategy(String.class), Mode.DESERIALIZE);
JsonObject json = gson.toJsonTree(testObj).getAsJsonObject();
assertEquals(testObj.annotatedField, json.get("annotatedField").getAsInt());
assertEquals(testObj.stringField, json.get("stringField").getAsString());
assertEquals(testObj.longField, json.get("longField").getAsLong());
SampleObjectForTest target = gson.fromJson(json, SampleObjectForTest.class);
assertEquals(testObj.longField, target.longField);
// assert excluded fields are set to the defaults
assertEquals(src.annotatedField, target.annotatedField);
assertEquals(src.stringField, target.stringField);
}
private static Gson createGson(ExclusionStrategy exclusionStrategy, Mode mode) {
GsonBuilder gsonBuilder = new GsonBuilder();
if (mode == null) {
gsonBuilder.setExclusionStrategies(exclusionStrategy);
} else {
gsonBuilder.setExclusionStrategies(mode, exclusionStrategy);
}
return gsonBuilder
.serializeNulls() .serializeNulls()
.create(); .create();
} }
@ -117,13 +113,15 @@ public class ExclusionStrategyFunctionalTest extends TestCase {
private final int annotatedField; private final int annotatedField;
private final String stringField; private final String stringField;
private final long longField; private final long longField;
private final Class<?> clazzField;
public SampleObjectForTest() { public SampleObjectForTest() {
annotatedField = 5; this(5, "someDefaultValue", 12345L);
stringField = "someDefaultValue"; }
longField = 1234;
clazzField = String.class; public SampleObjectForTest(int annotatedField, String stringField, long longField) {
this.annotatedField = annotatedField;
this.stringField = stringField;
this.longField = longField;
} }
} }