diff --git a/gson/src/main/java/com/google/gson/AnonymousAndLocalClassExclusionStrategy.java b/gson/src/main/java/com/google/gson/AnonymousAndLocalClassExclusionStrategy.java index 7d48cb0e..28ae1448 100644 --- a/gson/src/main/java/com/google/gson/AnonymousAndLocalClassExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/AnonymousAndLocalClassExclusionStrategy.java @@ -16,19 +16,18 @@ package com.google.gson; - /** * Strategy for excluding anonymous and local classes. * * @author Joel Leitch */ -final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy { +final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy2 { - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return isAnonymousOrLocal(f.getDeclaredClass()); } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return isAnonymousOrLocal(clazz); } diff --git a/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java b/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java index c7974b1a..a2ffb70f 100644 --- a/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java @@ -19,31 +19,31 @@ package com.google.gson; import java.util.Collection; /** - * A wrapper class used to collect numerous {@link ExclusionStrategy} objects + * A wrapper class used to collect numerous {@link ExclusionStrategy2} objects * and perform a short-circuited OR operation. * * @author Joel Leitch */ -final class DisjunctionExclusionStrategy implements ExclusionStrategy { - private final Collection strategies; +final class DisjunctionExclusionStrategy implements ExclusionStrategy2 { + private final Collection strategies; - public DisjunctionExclusionStrategy(Collection strategies) { + public DisjunctionExclusionStrategy(Collection strategies) { Preconditions.checkNotNull(strategies); this.strategies = strategies; } - public boolean shouldSkipField(FieldAttributes f) { - for (ExclusionStrategy strategy : strategies) { - if (strategy.shouldSkipField(f)) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { + for (ExclusionStrategy2 strategy : strategies) { + if (strategy.shouldSkipField(f, mode)) { return true; } } return false; } - public boolean shouldSkipClass(Class clazz) { - for (ExclusionStrategy strategy : strategies) { - if (strategy.shouldSkipClass(clazz)) { + public boolean shouldSkipClass(Class clazz, Mode mode) { + for (ExclusionStrategy2 strategy : strategies) { + if (strategy.shouldSkipClass(clazz, mode)) { return true; } } diff --git a/gson/src/main/java/com/google/gson/ExclusionStrategy.java b/gson/src/main/java/com/google/gson/ExclusionStrategy.java index 702d7e96..a83c5da6 100644 --- a/gson/src/main/java/com/google/gson/ExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/ExclusionStrategy.java @@ -78,7 +78,9 @@ package com.google.gson; * @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...) * * @since 1.4 + * @deprecated use the more powerful {@link ExclusionStrategy2} instead. */ +@Deprecated public interface ExclusionStrategy { /** diff --git a/gson/src/main/java/com/google/gson/ExclusionStrategy2.java b/gson/src/main/java/com/google/gson/ExclusionStrategy2.java new file mode 100644 index 00000000..cd67e9bd --- /dev/null +++ b/gson/src/main/java/com/google/gson/ExclusionStrategy2.java @@ -0,0 +1,125 @@ +/* + * 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. + * + *

The following are a few examples that shows how you can use this exclusion mechanism. + * + *

Exclude fields and objects based on a particular class type for both serialization + * and deserialization: + *

+ * public class SpecificClassExclusionStrategy implements ExclusionStrategy2 {
+ *   private final Class<?> excludedThisClass;
+ *
+ *   public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
+ *     this.excludedThisClass = excludedThisClass;
+ *   }
+ *
+ *   public boolean shouldSkipClass(Class<?> clazz, Context context) {
+ *     return excludedThisClass.equals(clazz);
+ *   }
+ *
+ *   public boolean shouldSkipField(FieldAttributes f, Context context) {
+ *     return excludedThisClass.equals(f.getDeclaredClass());
+ *   }
+ * }
+ * 
+ * + *

Excludes fields and objects based on a particular annotation for both serialization + * and deserialization: + *

+ * public @interface FooAnnotation {
+ *   // some implementation here
+ * }
+ *
+ * // Excludes any field (or class) that is tagged with an "@FooAnnotation"
+ * public class FooAnnotationExclusionStrategy implements ExclusionStrategy2 {
+ *   public boolean shouldSkipClass(Class<?> clazz, Context context) {
+ *     return clazz.getAnnotation(FooAnnotation.class) != null;
+ *   }
+ *
+ *   public boolean shouldSkipField(FieldAttributes f, Context context) {
+ *     return f.getAnnotation(FooAnnotation.class) != null;
+ *   }
+ * }
+ * 
+ * + *

Exclude fields and objects based on a particular class type for serialization + * only: + *

+ * public class SpecificClassExclusionStrategy implements ExclusionStrategy2 {
+ *   private final Class<?> excludedThisClass;
+ *
+ *   public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
+ *     this.excludedThisClass = excludedThisClass;
+ *   }
+ *
+ *   public boolean shouldSkipClass(Class<?> 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;
+ *     }
+ *   }
+ * }
+ * 
+ * + *

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: + *

+ * ExclusionStrategy2 excludeStrings = new UserDefinedExclusionStrategy(String.class);
+ * Gson gson = new GsonBuilder()
+ *     .setExclusionStrategies(excludeStrings)
+ *     .create();
+ * 
+ * + * @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); +} diff --git a/gson/src/main/java/com/google/gson/ExclusionStrategy2Adapter.java b/gson/src/main/java/com/google/gson/ExclusionStrategy2Adapter.java new file mode 100644 index 00000000..da24f0fb --- /dev/null +++ b/gson/src/main/java/com/google/gson/ExclusionStrategy2Adapter.java @@ -0,0 +1,39 @@ +/* + * 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; + +/** + * Adapts the old {@link ExclusionStrategy} into the newer {@link ExclusionStrategy2} type. + * + * @author Joel Leitch + */ +class ExclusionStrategy2Adapter implements ExclusionStrategy2 { + private final ExclusionStrategy strategy; + + public ExclusionStrategy2Adapter(ExclusionStrategy strategy) { + Preconditions.checkNotNull(strategy); + this.strategy = strategy; + } + + public boolean shouldSkipClass(Class clazz, Mode mode) { + return strategy.shouldSkipClass(clazz); + } + + public boolean shouldSkipField(FieldAttributes f, Mode mode) { + return strategy.shouldSkipField(f); + } +} diff --git a/gson/src/main/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategy.java b/gson/src/main/java/com/google/gson/ExposeAnnotationExclusionStrategy.java similarity index 67% rename from gson/src/main/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategy.java rename to gson/src/main/java/com/google/gson/ExposeAnnotationExclusionStrategy.java index e248d702..9d0ece5a 100644 --- a/gson/src/main/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/ExposeAnnotationExclusionStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Google Inc. + * 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. @@ -21,20 +21,25 @@ import com.google.gson.annotations.Expose; /** * Excludes fields that do not have the {@link Expose} annotation * - * @author Inderjeet Singh * @author Joel Leitch */ -final class ExposeAnnotationSerializationExclusionStrategy implements ExclusionStrategy { - - public boolean shouldSkipClass(Class clazz) { +public class ExposeAnnotationExclusionStrategy implements ExclusionStrategy2 { + public boolean shouldSkipClass(Class clazz, Mode mode) { return false; } - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { Expose annotation = f.getAnnotation(Expose.class); if (annotation == null) { return true; } - return !annotation.serialize(); + + if (mode == Mode.SERIALIZE) { + return !annotation.serialize(); + } else if (mode == Mode.DESERIALIZE) { + return !annotation.deserialize(); + } + + return false; } } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index c6177659..84ec2d9e 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -92,15 +92,11 @@ public final class Gson { static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY = new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy()); - private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = - createExclusionStrategy(VersionConstants.IGNORE_VERSIONS); + private static final ExclusionStrategy2 DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy(); private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; - private final ExclusionStrategy serializationStrategy; - - private final ExclusionStrategy deserializationStrategy; - + private final ExclusionStrategy2 exclusionStrategy; private final FieldNamingStrategy2 fieldNamingPolicy; private final MappedObjectConstructor objectConstructor; @@ -150,19 +146,18 @@ public final class Gson { * */ public Gson() { - this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY, + this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY, new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), false, DefaultTypeAdapters.getAllDefaultSerializers(), DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false); } - Gson(ExclusionStrategy serializationStrategy, ExclusionStrategy deserializationStrategy, - FieldNamingStrategy2 fieldNamingPolicy, MappedObjectConstructor objectConstructor, - boolean serializeNulls, ParameterizedTypeHandlerMap> serializers, - ParameterizedTypeHandlerMap> deserializers, - boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) { - this.serializationStrategy = serializationStrategy; - this.deserializationStrategy = deserializationStrategy; + Gson(ExclusionStrategy2 exclusionStrategy, FieldNamingStrategy2 fieldNamingPolicy, + MappedObjectConstructor objectConstructor, boolean serializeNulls, + ParameterizedTypeHandlerMap> serializers, + ParameterizedTypeHandlerMap> deserializers, + boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) { + this.exclusionStrategy = exclusionStrategy; this.fieldNamingPolicy = fieldNamingPolicy; this.objectConstructor = objectConstructor; this.serializeNulls = serializeNulls; @@ -173,18 +168,15 @@ public final class Gson { this.prettyPrinting = prettyPrinting; } - private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy strategy) { + private ObjectNavigatorFactory createDefaultObjectNavigatorFactory(ExclusionStrategy2 strategy) { return new ObjectNavigatorFactory(strategy, fieldNamingPolicy); } - private static ExclusionStrategy createExclusionStrategy(double version) { - List strategies = new LinkedList(); + private static ExclusionStrategy2 createExclusionStrategy() { + List strategies = new LinkedList(); strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY); strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY); strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY); - if (version != VersionConstants.IGNORE_VERSIONS) { - strategies.add(new VersionExclusionStrategy(version)); - } return new DisjunctionExclusionStrategy(strategies); } @@ -229,7 +221,7 @@ public final class Gson { return JsonNull.createJsonNull(); } JsonSerializationContextDefault context = new JsonSerializationContextDefault( - createDefaultObjectNavigatorFactory(serializationStrategy), serializeNulls, serializers); + createDefaultObjectNavigatorFactory(exclusionStrategy), serializeNulls, serializers); return context.serialize(src, typeOfSrc, true); } @@ -563,7 +555,7 @@ public final class Gson { return null; } JsonDeserializationContext context = new JsonDeserializationContextDefault( - createDefaultObjectNavigatorFactory(deserializationStrategy), deserializers, + createDefaultObjectNavigatorFactory(exclusionStrategy), deserializers, objectConstructor); T target = (T) context.deserialize(json, typeOfT); return target; diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index 17150314..452c26e9 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -54,15 +54,11 @@ import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter; public final class GsonBuilder { private static final InnerClassExclusionStrategy innerClassExclusionStrategy = new InnerClassExclusionStrategy(); - private static final ExposeAnnotationSerializationExclusionStrategy - exposeAnnotationSerializationExclusionStrategy = - new ExposeAnnotationSerializationExclusionStrategy(); - private static final ExposeAnnotationDeserializationExclusionStrategy - exposeAnnotationDeserializationExclusionStrategy = - new ExposeAnnotationDeserializationExclusionStrategy(); + private static final ExposeAnnotationExclusionStrategy exposeAnnotationExclusionStrategy = + new ExposeAnnotationExclusionStrategy(); - private final Collection exclusionStrategies = - new HashSet(); + private final Collection exclusionStrategies = + new HashSet(); private double ignoreVersionsAfter; private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy; @@ -247,9 +243,30 @@ public final class GsonBuilder { * @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 + * @deprecated convert your {@code strategies} to {@link ExclusionStrategy2} and use the + * {@link #setExclusionStrategies(ExclusionStrategy2...) method instead. */ + @Deprecated public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) { for (ExclusionStrategy strategy : strategies) { + exclusionStrategies.add(new ExclusionStrategy2Adapter(strategy)); + } + 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 disjunction rule. + * 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 + * mode. + * + * @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.7 + */ + public GsonBuilder setExclusionStrategies(ExclusionStrategy2... strategies) { + for (ExclusionStrategy2 strategy : strategies) { exclusionStrategies.add(strategy); } return this; @@ -497,30 +514,20 @@ public final class GsonBuilder { * @return an instance of Gson configured with the options currently set in this builder */ public Gson create() { - List serializationStrategies = - new LinkedList(exclusionStrategies); - List deserializationStrategies = - new LinkedList(exclusionStrategies); - - serializationStrategies.add(modifierBasedExclusionStrategy); - deserializationStrategies.add(modifierBasedExclusionStrategy); + List strategies = + new LinkedList(exclusionStrategies); + strategies.add(modifierBasedExclusionStrategy); if (!serializeInnerClasses) { - serializationStrategies.add(innerClassExclusionStrategy); - deserializationStrategies.add(innerClassExclusionStrategy); + strategies.add(innerClassExclusionStrategy); } if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) { - serializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter)); - deserializationStrategies.add(new VersionExclusionStrategy(ignoreVersionsAfter)); + strategies.add(new VersionExclusionStrategy(ignoreVersionsAfter)); } if (excludeFieldsWithoutExposeAnnotation) { - serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy); - deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy); + strategies.add(exposeAnnotationExclusionStrategy); } - ExclusionStrategy serializationExclusionStrategy = - new DisjunctionExclusionStrategy(serializationStrategies); - ExclusionStrategy deserializationExclusionStrategy = - new DisjunctionExclusionStrategy(deserializationStrategies); + ExclusionStrategy2 exclusionStrategy = new DisjunctionExclusionStrategy(strategies); ParameterizedTypeHandlerMap> customSerializers = DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf(); @@ -546,9 +553,9 @@ public final class GsonBuilder { MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators); - Gson gson = new Gson(serializationExclusionStrategy, deserializationExclusionStrategy, - fieldNamingPolicy, objConstructor, serializeNulls, customSerializers, - customDeserializers, generateNonExecutableJson, escapeHtmlChars, prettyPrinting); + Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor, serializeNulls, + customSerializers, customDeserializers, generateNonExecutableJson, escapeHtmlChars, + prettyPrinting); return gson; } diff --git a/gson/src/main/java/com/google/gson/InnerClassExclusionStrategy.java b/gson/src/main/java/com/google/gson/InnerClassExclusionStrategy.java index e125bfae..6dda7e4f 100644 --- a/gson/src/main/java/com/google/gson/InnerClassExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/InnerClassExclusionStrategy.java @@ -23,13 +23,13 @@ import java.lang.reflect.Modifier; * * @author Joel Leitch */ -class InnerClassExclusionStrategy implements ExclusionStrategy { +class InnerClassExclusionStrategy implements ExclusionStrategy2 { - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return isInnerClass(f.getDeclaredClass()); } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return isInnerClass(clazz); } diff --git a/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java b/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java index edae425f..02644e57 100644 --- a/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java +++ b/gson/src/main/java/com/google/gson/JsonDeserializationVisitor.java @@ -58,6 +58,10 @@ abstract class JsonDeserializationVisitor implements ObjectNavigator.Visitor } return target; } + + public Mode getMode() { + return Mode.DESERIALIZE; + } protected abstract T constructTarget(); diff --git a/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java b/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java index 0649a5a7..6d0e3917 100644 --- a/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java +++ b/gson/src/main/java/com/google/gson/JsonSerializationVisitor.java @@ -47,6 +47,10 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor { public Object getTarget() { return null; } + + public Mode getMode() { + return Mode.SERIALIZE; + } public void start(ObjectTypePair node) { if (node == null) { diff --git a/gson/src/main/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategy.java b/gson/src/main/java/com/google/gson/Mode.java similarity index 53% rename from gson/src/main/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategy.java rename to gson/src/main/java/com/google/gson/Mode.java index c087e81f..47fa4cfa 100644 --- a/gson/src/main/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/Mode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. + * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.google.gson; -import com.google.gson.annotations.Expose; - /** - * Excludes fields that do not have the {@link Expose} annotation + * Defines the current context of Gson so that common code for serializing and deserializing can + * distinguish between the two modes. * - * @author Inderjeet Singh * @author Joel Leitch + * + * @since 1.7 */ -final class ExposeAnnotationDeserializationExclusionStrategy implements ExclusionStrategy { - - public boolean shouldSkipClass(Class clazz) { - return false; - } - - public boolean shouldSkipField(FieldAttributes f) { - Expose annotation = f.getAnnotation(Expose.class); - if (annotation == null) { - return true; - } - return !annotation.deserialize(); - } +public enum Mode { + SERIALIZE, + DESERIALIZE; } diff --git a/gson/src/main/java/com/google/gson/ModifierBasedExclusionStrategy.java b/gson/src/main/java/com/google/gson/ModifierBasedExclusionStrategy.java index fdf8e5ba..fa8bffc9 100644 --- a/gson/src/main/java/com/google/gson/ModifierBasedExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/ModifierBasedExclusionStrategy.java @@ -26,7 +26,7 @@ import java.util.HashSet; * @author Inderjeet Singh * @author Joel Leitch */ -final class ModifierBasedExclusionStrategy implements ExclusionStrategy { +final class ModifierBasedExclusionStrategy implements ExclusionStrategy2 { private final Collection modifiers; public ModifierBasedExclusionStrategy(int... modifiers) { @@ -38,7 +38,7 @@ final class ModifierBasedExclusionStrategy implements ExclusionStrategy { } } - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { for (int modifier : modifiers) { if (f.hasModifier(modifier)) { return true; @@ -47,7 +47,7 @@ final class ModifierBasedExclusionStrategy implements ExclusionStrategy { return false; } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return false; } } diff --git a/gson/src/main/java/com/google/gson/NullExclusionStrategy.java b/gson/src/main/java/com/google/gson/NullExclusionStrategy.java index c7a1bafa..5f9a806a 100644 --- a/gson/src/main/java/com/google/gson/NullExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/NullExclusionStrategy.java @@ -16,22 +16,21 @@ package com.google.gson; - /** - * This acts as a "Null Object" pattern for the {@link ExclusionStrategy}. + * This acts as a "Null Object" pattern for the {@link ExclusionStrategy2}. * Passing an instance of this class into the {@link ObjectNavigator} will * make the {@link ObjectNavigator} parse/visit every field of the object * being navigated. * * @author Joel Leitch */ -final class NullExclusionStrategy implements ExclusionStrategy { +final class NullExclusionStrategy implements ExclusionStrategy2 { - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return false; } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return false; } } diff --git a/gson/src/main/java/com/google/gson/ObjectNavigator.java b/gson/src/main/java/com/google/gson/ObjectNavigator.java index 0738c709..2eefd57f 100644 --- a/gson/src/main/java/com/google/gson/ObjectNavigator.java +++ b/gson/src/main/java/com/google/gson/ObjectNavigator.java @@ -69,15 +69,17 @@ final class ObjectNavigator { public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField, Object parent); + void visitPrimitive(Object primitive); + /** * Retrieve the current target */ Object getTarget(); - - void visitPrimitive(Object primitive); + + Mode getMode(); } - private final ExclusionStrategy exclusionStrategy; + private final ExclusionStrategy2 exclusionStrategy; private final ObjectTypePair objTypePair; /** @@ -87,7 +89,7 @@ final class ObjectNavigator { * the concrete strategy object to be used to filter out fields of an * object. */ - ObjectNavigator(ObjectTypePair objTypePair, ExclusionStrategy exclusionStrategy) { + ObjectNavigator(ObjectTypePair objTypePair, ExclusionStrategy2 exclusionStrategy) { Preconditions.checkNotNull(exclusionStrategy); this.objTypePair = objTypePair; @@ -99,7 +101,7 @@ final class ObjectNavigator { * does not get visited. */ public void accept(Visitor visitor) { - if (exclusionStrategy.shouldSkipClass(Types.getRawType(objTypePair.type))) { + if (exclusionStrategy.shouldSkipClass(Types.getRawType(objTypePair.type), visitor.getMode())) { return; } boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair); @@ -143,12 +145,13 @@ final class ObjectNavigator { } private void navigateClassFields(Object obj, Class clazz, Visitor visitor) { + Mode mode = visitor.getMode(); Field[] fields = clazz.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); for (Field f : fields) { FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); - if (exclusionStrategy.shouldSkipField(fieldAttributes) - || exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) { + if (exclusionStrategy.shouldSkipField(fieldAttributes, mode) + || exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass(), mode)) { continue; // skip } Type declaredTypeOfField = getTypeInfoForField(f, objTypePair.type); diff --git a/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java b/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java index 3f90cea3..b2e501e1 100644 --- a/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java +++ b/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java @@ -18,13 +18,13 @@ package com.google.gson; /** * A factory class used to simplify {@link ObjectNavigator} creation. - * This object holds on to a reference of the {@link ExclusionStrategy} + * This object holds on to a reference of the {@link ExclusionStrategy2} * that you'd like to use with the {@link ObjectNavigator}. * * @author Joel Leitch */ final class ObjectNavigatorFactory { - private final ExclusionStrategy strategy; + private final ExclusionStrategy2 strategy; private final FieldNamingStrategy2 fieldNamingPolicy; /** @@ -36,7 +36,7 @@ final class ObjectNavigatorFactory { * @param fieldNamingPolicy the naming policy that should be applied to field * names */ - public ObjectNavigatorFactory(ExclusionStrategy strategy, FieldNamingStrategy2 fieldNamingPolicy) { + public ObjectNavigatorFactory(ExclusionStrategy2 strategy, FieldNamingStrategy2 fieldNamingPolicy) { Preconditions.checkNotNull(fieldNamingPolicy); this.strategy = (strategy == null ? new NullExclusionStrategy() : strategy); this.fieldNamingPolicy = fieldNamingPolicy; diff --git a/gson/src/main/java/com/google/gson/SyntheticFieldExclusionStrategy.java b/gson/src/main/java/com/google/gson/SyntheticFieldExclusionStrategy.java index ab90c5d0..8c575916 100644 --- a/gson/src/main/java/com/google/gson/SyntheticFieldExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/SyntheticFieldExclusionStrategy.java @@ -26,18 +26,18 @@ package com.google.gson; * * @since 1.4 */ -class SyntheticFieldExclusionStrategy implements ExclusionStrategy { +class SyntheticFieldExclusionStrategy implements ExclusionStrategy2 { private final boolean skipSyntheticFields; SyntheticFieldExclusionStrategy(boolean skipSyntheticFields) { this.skipSyntheticFields = skipSyntheticFields; } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return false; } - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return skipSyntheticFields && f.isSynthetic(); } diff --git a/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java b/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java index 8bd726f3..498e35f9 100644 --- a/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java @@ -25,7 +25,7 @@ import com.google.gson.annotations.Until; * * @author Joel Leitch */ -final class VersionExclusionStrategy implements ExclusionStrategy { +final class VersionExclusionStrategy implements ExclusionStrategy2 { private final double version; public VersionExclusionStrategy(double version) { @@ -33,11 +33,11 @@ final class VersionExclusionStrategy implements ExclusionStrategy { this.version = version; } - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class)); } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class)); } diff --git a/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java index 34fcccb8..47d9cd76 100644 --- a/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java +++ b/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java @@ -28,35 +28,38 @@ import junit.framework.TestCase; */ public class DisjunctionExclusionStrategyTest extends TestCase { - private static final ExclusionStrategy FALSE_STRATEGY = new MockExclusionStrategy(false, false); - private static final ExclusionStrategy TRUE_STRATEGY = new MockExclusionStrategy(true, true); + private static final ExclusionStrategy2 FALSE_STRATEGY = + new MockExclusionStrategy2(false, false, null); + private static final ExclusionStrategy2 TRUE_STRATEGY = + new MockExclusionStrategy2(true, true, null); + private static final Class CLAZZ = String.class; private static final FieldAttributes FIELD = new FieldAttributes(CLAZZ, CLAZZ.getFields()[0]); public void testBadInstantiation() throws Exception { try { - List constructorParam = null; + List constructorParam = null; new DisjunctionExclusionStrategy(constructorParam); fail("Should throw an exception"); } catch (IllegalArgumentException expected) { } } public void testSkipFieldsWithMixedTrueAndFalse() throws Exception { - List strategies = new LinkedList(); + List strategies = new LinkedList(); strategies.add(FALSE_STRATEGY); strategies.add(TRUE_STRATEGY); DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); - assertTrue(strategy.shouldSkipClass(CLAZZ)); - assertTrue(strategy.shouldSkipField(FIELD)); + assertTrue(strategy.shouldSkipClass(CLAZZ, Mode.SERIALIZE)); + assertTrue(strategy.shouldSkipField(FIELD, Mode.SERIALIZE)); } public void testSkipFieldsWithFalseOnly() throws Exception { - List strategies = new LinkedList(); + List strategies = new LinkedList(); strategies.add(FALSE_STRATEGY); DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); - assertFalse(strategy.shouldSkipClass(CLAZZ)); - assertFalse(strategy.shouldSkipField(FIELD)); + assertFalse(strategy.shouldSkipClass(CLAZZ, Mode.SERIALIZE)); + assertFalse(strategy.shouldSkipField(FIELD, Mode.SERIALIZE)); } } diff --git a/gson/src/test/java/com/google/gson/ExclusionStrategy2AdapterTest.java b/gson/src/test/java/com/google/gson/ExclusionStrategy2AdapterTest.java new file mode 100644 index 00000000..173dcbd4 --- /dev/null +++ b/gson/src/test/java/com/google/gson/ExclusionStrategy2AdapterTest.java @@ -0,0 +1,47 @@ +/* + * 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)); + } +} diff --git a/gson/src/test/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategyTest.java deleted file mode 100644 index 8fcdb577..00000000 --- a/gson/src/test/java/com/google/gson/ExposeAnnotationDeserializationExclusionStrategyTest.java +++ /dev/null @@ -1,76 +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; - -import java.lang.reflect.Field; - -import junit.framework.TestCase; - -import com.google.gson.annotations.Expose; - -/** - * Unit tests for the {@link ExposeAnnotationDeserializationExclusionStrategy} class. - * - * @author Joel Leitch - */ -public class ExposeAnnotationDeserializationExclusionStrategyTest extends TestCase { - private ExposeAnnotationDeserializationExclusionStrategy strategy; - - @Override - protected void setUp() throws Exception { - super.setUp(); - strategy = new ExposeAnnotationDeserializationExclusionStrategy(); - } - - public void testNeverSkipClasses() throws Exception { - assertFalse(strategy.shouldSkipClass(MockObject.class)); - } - - public void testSkipNonAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("hiddenField"); - assertTrue(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testSkipExplicitlySkippedFields() throws Exception { - Field f = MockObject.class.getField("explicitlyHiddenField"); - assertTrue(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testNeverSkipExposedAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("exposedField"); - assertFalse(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("explicitlyExposedField"); - assertFalse(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - @SuppressWarnings("unused") - private static class MockObject { - @Expose - public final int exposedField = 0; - - @Expose(deserialize=true) - public final int explicitlyExposedField = 0; - - @Expose(deserialize=false) - public final int explicitlyHiddenField = 0; - - public final int hiddenField = 0; - } -} diff --git a/gson/src/test/java/com/google/gson/ExposeAnnotationExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/ExposeAnnotationExclusionStrategyTest.java new file mode 100644 index 00000000..db040a4b --- /dev/null +++ b/gson/src/test/java/com/google/gson/ExposeAnnotationExclusionStrategyTest.java @@ -0,0 +1,95 @@ +/* + * 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 com.google.gson.annotations.Expose; + +import junit.framework.TestCase; + +/** + * Unit tests for the {@link ExposeAnnotationExclusionStrategy} class. + * + * @author Joel Leitch + */ +public class ExposeAnnotationExclusionStrategyTest extends TestCase { + private ExposeAnnotationExclusionStrategy strategy; + + @Override + protected void setUp() throws Exception { + super.setUp(); + strategy = new ExposeAnnotationExclusionStrategy(); + } + + public void testNeverSkipClasses() throws Exception { + assertFalse(strategy.shouldSkipClass(MockObject.class, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipClass(MockObject.class, Mode.SERIALIZE)); + } + + public void testSkipNonAnnotatedFields() throws Exception { + FieldAttributes f = createFieldAttributes("hiddenField"); + assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); + assertTrue(strategy.shouldSkipField(f, Mode.SERIALIZE)); + } + + public void testSkipExplicitlySkippedFields() throws Exception { + FieldAttributes f = createFieldAttributes("explicitlyHiddenField"); + assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); + assertTrue(strategy.shouldSkipField(f, Mode.SERIALIZE)); + } + + public void testNeverSkipExposedAnnotatedFields() throws Exception { + FieldAttributes f = createFieldAttributes("exposedField"); + assertFalse(strategy.shouldSkipField(f, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); + } + + public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception { + FieldAttributes f = createFieldAttributes("explicitlyExposedField"); + assertFalse(strategy.shouldSkipField(f, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); + } + + public void testDifferentSerializeAndDeserializeField() throws Exception { + FieldAttributes f = createFieldAttributes("explicitlyDifferentModeField"); + assertTrue(strategy.shouldSkipField(f, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipField(f, Mode.SERIALIZE)); + } + + private static FieldAttributes createFieldAttributes(String fieldName) throws Exception { + Field f = MockObject.class.getField(fieldName); + return new FieldAttributes(MockObject.class, f); + } + + @SuppressWarnings("unused") + private static class MockObject { + @Expose + public final int exposedField = 0; + + @Expose(serialize=true, deserialize=true) + public final int explicitlyExposedField = 0; + + @Expose(serialize=false, deserialize=false) + public final int explicitlyHiddenField = 0; + + @Expose(serialize=true, deserialize=false) + public final int explicitlyDifferentModeField = 0; + + public final int hiddenField = 0; + } +} diff --git a/gson/src/test/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategyTest.java deleted file mode 100644 index 08ead177..00000000 --- a/gson/src/test/java/com/google/gson/ExposeAnnotationSerializationExclusionStrategyTest.java +++ /dev/null @@ -1,76 +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; - -import java.lang.reflect.Field; - -import junit.framework.TestCase; - -import com.google.gson.annotations.Expose; - -/** - * Unit tests for the {@link ExposeAnnotationSerializationExclusionStrategy} class. - * - * @author Joel Leitch - */ -public class ExposeAnnotationSerializationExclusionStrategyTest extends TestCase { - private ExposeAnnotationSerializationExclusionStrategy strategy; - - @Override - protected void setUp() throws Exception { - super.setUp(); - strategy = new ExposeAnnotationSerializationExclusionStrategy(); - } - - public void testNeverSkipClasses() throws Exception { - assertFalse(strategy.shouldSkipClass(MockObject.class)); - } - - public void testSkipNonAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("hiddenField"); - assertTrue(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testSkipExplicitlySkippedFields() throws Exception { - Field f = MockObject.class.getField("explicitlyHiddenField"); - assertTrue(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testNeverSkipExposedAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("exposedField"); - assertFalse(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - public void testNeverSkipExplicitlyExposedAnnotatedFields() throws Exception { - Field f = MockObject.class.getField("explicitlyExposedField"); - assertFalse(strategy.shouldSkipField(new FieldAttributes(MockObject.class, f))); - } - - @SuppressWarnings("unused") - private static class MockObject { - @Expose - public final int exposedField = 0; - - @Expose(serialize=true) - public final int explicitlyExposedField = 0; - - @Expose(serialize=false) - public final int explicitlyHiddenField = 0; - - public final int hiddenField = 0; - } -} diff --git a/gson/src/test/java/com/google/gson/FunctionWithInternalDependenciesTest.java b/gson/src/test/java/com/google/gson/FunctionWithInternalDependenciesTest.java index 736141f5..aee7f3ea 100644 --- a/gson/src/test/java/com/google/gson/FunctionWithInternalDependenciesTest.java +++ b/gson/src/test/java/com/google/gson/FunctionWithInternalDependenciesTest.java @@ -35,11 +35,11 @@ import com.google.gson.common.TestTypes.ClassWithNoFields; public class FunctionWithInternalDependenciesTest extends TestCase { public void testAnonymousLocalClassesSerialization() throws Exception { - LinkedList strategies = new LinkedList(); + LinkedList strategies = new LinkedList(); 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, + ExclusionStrategy2 exclusionStrategy = new DisjunctionExclusionStrategy(strategies); + Gson gson = new Gson(exclusionStrategy, Gson.DEFAULT_NAMING_POLICY, new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), false, DefaultTypeAdapters.getDefaultSerializers(), DefaultTypeAdapters.getDefaultDeserializers(), Gson.DEFAULT_JSON_NON_EXECUTABLE, true, @@ -60,18 +60,18 @@ public class FunctionWithInternalDependenciesTest extends TestCase { assertEquals("{}", json); } - private static class UserDefinedExclusionStrategy implements ExclusionStrategy { + private static class UserDefinedExclusionStrategy implements ExclusionStrategy2 { private final Class excludedThisClass; UserDefinedExclusionStrategy(Class excludedThisClass) { this.excludedThisClass = excludedThisClass; } - public boolean shouldSkipClass(Class clazz) { + public boolean shouldSkipClass(Class clazz, Mode mode) { return excludedThisClass.equals(clazz); } - public boolean shouldSkipField(FieldAttributes f) { + public boolean shouldSkipField(FieldAttributes f, Mode mode) { return excludedThisClass.equals(f.getDeclaredClass()); } diff --git a/gson/src/test/java/com/google/gson/InnerClassExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/InnerClassExclusionStrategyTest.java index 4f6c4aad..3fb10d4d 100644 --- a/gson/src/test/java/com/google/gson/InnerClassExclusionStrategyTest.java +++ b/gson/src/test/java/com/google/gson/InnerClassExclusionStrategyTest.java @@ -41,22 +41,26 @@ public class InnerClassExclusionStrategyTest extends TestCase { public void testExcludeInnerClassObject() throws Exception { Class clazz = innerClass.getClass(); - assertTrue(strategy.shouldSkipClass(clazz)); + assertTrue(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); + assertTrue(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE)); } public void testExcludeInnerClassField() throws Exception { Field f = getClass().getField("innerClass"); - assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f))); + assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.SERIALIZE)); + assertTrue(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.DESERIALIZE)); } public void testIncludeStaticNestedClassObject() throws Exception { Class clazz = staticNestedClass.getClass(); - assertFalse(strategy.shouldSkipClass(clazz)); + assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); + assertFalse(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE)); } public void testIncludeStaticNestedClassField() throws Exception { Field f = getClass().getField("staticNestedClass"); - assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f))); + assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.SERIALIZE)); + assertFalse(strategy.shouldSkipField(new FieldAttributes(getClass(), f), Mode.DESERIALIZE)); } class InnerClass { diff --git a/gson/src/test/java/com/google/gson/MockExclusionStrategy.java b/gson/src/test/java/com/google/gson/MockExclusionStrategy.java index 6b7a3bab..cc105f51 100644 --- a/gson/src/test/java/com/google/gson/MockExclusionStrategy.java +++ b/gson/src/test/java/com/google/gson/MockExclusionStrategy.java @@ -16,7 +16,6 @@ package com.google.gson; - /** * This is a configurable {@link ExclusionStrategy} that can be used for * unit testing. diff --git a/gson/src/test/java/com/google/gson/MockExclusionStrategy2.java b/gson/src/test/java/com/google/gson/MockExclusionStrategy2.java new file mode 100644 index 00000000..28d2dc51 --- /dev/null +++ b/gson/src/test/java/com/google/gson/MockExclusionStrategy2.java @@ -0,0 +1,49 @@ +/* + * 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; + } + } +} diff --git a/gson/src/test/java/com/google/gson/NullExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/NullExclusionStrategyTest.java index 7710db19..12b0b1c0 100644 --- a/gson/src/test/java/com/google/gson/NullExclusionStrategyTest.java +++ b/gson/src/test/java/com/google/gson/NullExclusionStrategyTest.java @@ -33,11 +33,16 @@ public class NullExclusionStrategyTest extends TestCase { } public void testNeverSkipsClass() throws Exception { - assertFalse(strategy.shouldSkipClass(String.class)); + assertFalse(strategy.shouldSkipClass(String.class, Mode.SERIALIZE)); + assertFalse(strategy.shouldSkipClass(String.class, Mode.DESERIALIZE)); } public void testNeverSkipsField() throws Exception { 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)); } } diff --git a/gson/src/test/java/com/google/gson/VersionExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/VersionExclusionStrategyTest.java index 26263816..cdda45ab 100644 --- a/gson/src/test/java/com/google/gson/VersionExclusionStrategyTest.java +++ b/gson/src/test/java/com/google/gson/VersionExclusionStrategyTest.java @@ -42,8 +42,12 @@ public class VersionExclusionStrategyTest extends TestCase { Field f = clazz.getField("someField"); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION); - assertFalse(strategy.shouldSkipClass(clazz)); - assertFalse(strategy.shouldSkipField(new FieldAttributes(clazz, f))); + assertFalse(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); + + FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); + assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE)); } public void testClassAndFieldAreBehindInVersion() throws Exception { @@ -51,8 +55,12 @@ public class VersionExclusionStrategyTest extends TestCase { Field f = clazz.getField("someField"); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION + 1); - assertFalse(strategy.shouldSkipClass(clazz)); - assertFalse(strategy.shouldSkipField(new FieldAttributes(clazz, f))); + assertFalse(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); + + FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); + assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); + assertFalse(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE)); } public void testClassAndFieldAreAheadInVersion() throws Exception { @@ -60,8 +68,12 @@ public class VersionExclusionStrategyTest extends TestCase { Field f = clazz.getField("someField"); VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION - 1); - assertTrue(strategy.shouldSkipClass(clazz)); - assertTrue(strategy.shouldSkipField(new FieldAttributes(clazz, f))); + assertTrue(strategy.shouldSkipClass(clazz, Mode.DESERIALIZE)); + assertTrue(strategy.shouldSkipClass(clazz, Mode.SERIALIZE)); + + FieldAttributes fieldAttributes = new FieldAttributes(clazz, f); + assertTrue(strategy.shouldSkipField(fieldAttributes, Mode.DESERIALIZE)); + assertTrue(strategy.shouldSkipField(fieldAttributes, Mode.SERIALIZE)); } @Since(VERSION) diff --git a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java index 89d8ad38..097b8684 100644 --- a/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java +++ b/gson/src/test/java/com/google/gson/functional/DefaultTypeAdaptersTest.java @@ -225,9 +225,9 @@ public class DefaultTypeAdaptersTest extends TestCase { // millisecond portion. @SuppressWarnings("deprecation") private void assertEqualsDate(Date date, int year, int month, int day) { - assertEquals(year-1900, date.getYear()); - assertEquals(month, date.getMonth()); - assertEquals(day, date.getDate()); + assertEquals(year-1900, date.getYear()); + assertEquals(month, date.getMonth()); + assertEquals(day, date.getDate()); } @SuppressWarnings("deprecation") diff --git a/gson/src/test/java/com/google/gson/functional/ExclusionStrategyFunctionalTest.java b/gson/src/test/java/com/google/gson/functional/ExclusionStrategyFunctionalTest.java index db10ecfc..34f927bc 100644 --- a/gson/src/test/java/com/google/gson/functional/ExclusionStrategyFunctionalTest.java +++ b/gson/src/test/java/com/google/gson/functional/ExclusionStrategyFunctionalTest.java @@ -17,11 +17,15 @@ package com.google.gson.functional; import com.google.gson.ExclusionStrategy; +import com.google.gson.ExclusionStrategy2; import com.google.gson.FieldAttributes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import com.google.gson.MockExclusionStrategy; +import com.google.gson.MockExclusionStrategy2; +import com.google.gson.Mode; import junit.framework.TestCase; @@ -32,7 +36,7 @@ import java.lang.annotation.Target; /** * Performs some functional tests when Gson is instantiated with some common user defined - * {@link ExclusionStrategy} objects. + * {@link ExclusionStrategy} and {@link ExclusionStrategy2} objects. * * @author Inderjeet Singh * @author Joel Leitch @@ -52,11 +56,26 @@ public class ExclusionStrategyFunctionalTest extends TestCase { } public void testExclusionStrategySerialization() throws Exception { + Gson gson = createGson(new MyExclusionStrategy(String.class)); String json = gson.toJson(src); assertFalse(json.contains("\"stringField\"")); assertFalse(json.contains("\"annotatedField\"")); 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 { JsonObject json = new JsonObject(); @@ -72,6 +91,20 @@ public class ExclusionStrategyFunctionalTest extends TestCase { assertEquals(src.stringField, target.stringField); } + private static Gson createGson(ExclusionStrategy exclusionStrategy) { + return new GsonBuilder() + .setExclusionStrategies(exclusionStrategy) + .serializeNulls() + .create(); + } + + private static Gson createGson(ExclusionStrategy2 exclusionStrategy) { + return new GsonBuilder() + .setExclusionStrategies(exclusionStrategy) + .serializeNulls() + .create(); + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) private static @interface Foo {