Add new "Mode" enum and carry mode through Gson so exclusion strategies know whether it is currently serializing or deserializing.
Deprecate old ExclusionStrategy code since this new approach is more powerful.
This commit is contained in:
parent
2b9f81e8b5
commit
b883f8f4aa
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<ExclusionStrategy> strategies;
|
||||
final class DisjunctionExclusionStrategy implements ExclusionStrategy2 {
|
||||
private final Collection<ExclusionStrategy2> strategies;
|
||||
|
||||
public DisjunctionExclusionStrategy(Collection<ExclusionStrategy> strategies) {
|
||||
public DisjunctionExclusionStrategy(Collection<ExclusionStrategy2> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
125
gson/src/main/java/com/google/gson/ExclusionStrategy2.java
Normal file
125
gson/src/main/java/com/google/gson/ExclusionStrategy2.java
Normal file
@ -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.
|
||||
*
|
||||
* <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<?> 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());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p><strong>Excludes fields and objects based on a particular annotation for both serialization
|
||||
* and deserialization:</strong>
|
||||
* <pre class="code">
|
||||
* 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;
|
||||
* }
|
||||
* }
|
||||
* </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<?> 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;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 {
|
||||
* </ul>
|
||||
*/
|
||||
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<JsonSerializer<?>> serializers,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
|
||||
boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) {
|
||||
this.serializationStrategy = serializationStrategy;
|
||||
this.deserializationStrategy = deserializationStrategy;
|
||||
Gson(ExclusionStrategy2 exclusionStrategy, FieldNamingStrategy2 fieldNamingPolicy,
|
||||
MappedObjectConstructor objectConstructor, boolean serializeNulls,
|
||||
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
|
||||
ParameterizedTypeHandlerMap<JsonDeserializer<?>> 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<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||
private static ExclusionStrategy2 createExclusionStrategy() {
|
||||
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>();
|
||||
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;
|
||||
|
@ -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<ExclusionStrategy> exclusionStrategies =
|
||||
new HashSet<ExclusionStrategy>();
|
||||
private final Collection<ExclusionStrategy2> exclusionStrategies =
|
||||
new HashSet<ExclusionStrategy2>();
|
||||
|
||||
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<ExclusionStrategy> serializationStrategies =
|
||||
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||
List<ExclusionStrategy> deserializationStrategies =
|
||||
new LinkedList<ExclusionStrategy>(exclusionStrategies);
|
||||
|
||||
serializationStrategies.add(modifierBasedExclusionStrategy);
|
||||
deserializationStrategies.add(modifierBasedExclusionStrategy);
|
||||
List<ExclusionStrategy2> strategies =
|
||||
new LinkedList<ExclusionStrategy2>(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<JsonSerializer<?>> 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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,10 @@ abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public Mode getMode() {
|
||||
return Mode.DESERIALIZE;
|
||||
}
|
||||
|
||||
protected abstract T constructTarget();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
@ -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<Integer> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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<ExclusionStrategy> constructorParam = null;
|
||||
List<ExclusionStrategy2> constructorParam = null;
|
||||
new DisjunctionExclusionStrategy(constructorParam);
|
||||
fail("Should throw an exception");
|
||||
} catch (IllegalArgumentException expected) { }
|
||||
}
|
||||
|
||||
public void testSkipFieldsWithMixedTrueAndFalse() throws Exception {
|
||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>();
|
||||
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<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||
List<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -35,11 +35,11 @@ import com.google.gson.common.TestTypes.ClassWithNoFields;
|
||||
public class FunctionWithInternalDependenciesTest extends TestCase {
|
||||
|
||||
public void testAnonymousLocalClassesSerialization() throws Exception {
|
||||
LinkedList<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
||||
LinkedList<ExclusionStrategy2> strategies = new LinkedList<ExclusionStrategy2>();
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.google.gson;
|
||||
|
||||
|
||||
/**
|
||||
* This is a configurable {@link ExclusionStrategy} that can be used for
|
||||
* unit testing.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user