Create a single, monolithic class to manage all exclusion strategies. This gets our file size within target of 177KiB.
I intend to follow this up with a builder for our new class to avoid multiple-argument constructor calls.
This commit is contained in:
parent
0ff7d980c5
commit
fed332906d
@ -1,53 +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 com.google.gson.internal.$Gson$Preconditions;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper class used to collect numerous {@link ExclusionStrategy} objects
|
|
||||||
* and perform a short-circuited OR operation.
|
|
||||||
*
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
final class DisjunctionExclusionStrategy implements ExclusionStrategy {
|
|
||||||
private final Collection<ExclusionStrategy> strategies;
|
|
||||||
|
|
||||||
DisjunctionExclusionStrategy(Collection<ExclusionStrategy> strategies) {
|
|
||||||
this.strategies = $Gson$Preconditions.checkNotNull(strategies);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
for (ExclusionStrategy strategy : strategies) {
|
|
||||||
if (strategy.shouldSkipField(f)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
for (ExclusionStrategy strategy : strategies) {
|
|
||||||
if (strategy.shouldSkipClass(clazz)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,13 +45,13 @@ import java.io.Reader;
|
|||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -103,7 +103,9 @@ public final class Gson {
|
|||||||
|
|
||||||
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||||
|
|
||||||
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy();
|
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = new GsonExclusionStrategy(
|
||||||
|
GsonExclusionStrategy.IGNORE_VERSIONS, Modifier.TRANSIENT | Modifier.STATIC,
|
||||||
|
true, true, true, false, false);
|
||||||
|
|
||||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||||
|
|
||||||
@ -341,14 +343,6 @@ public final class Gson {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExclusionStrategy createExclusionStrategy() {
|
|
||||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
|
||||||
strategies.add(GsonBuilder.EXCLUDE_ANONYMOUS_AND_LOCAL);
|
|
||||||
strategies.add(GsonBuilder.EXCLUDE_SYNTHETIC_FIELDS);
|
|
||||||
strategies.add(GsonBuilder.EXCLUDE_TRANSIENT_AND_STATIC);
|
|
||||||
return new DisjunctionExclusionStrategy(strategies);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type adapter for {@code} type.
|
* Returns the type adapter for {@code} type.
|
||||||
*
|
*
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.annotations.Expose;
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import com.google.gson.internal.Primitives;
|
import com.google.gson.internal.Primitives;
|
||||||
import com.google.gson.internal.TypeMap;
|
import com.google.gson.internal.TypeMap;
|
||||||
@ -27,12 +26,8 @@ import java.lang.reflect.Type;
|
|||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
|
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
|
||||||
@ -68,78 +63,13 @@ import java.util.Set;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class GsonBuilder {
|
public final class GsonBuilder {
|
||||||
/** Strategy for excluding inner classes. */
|
private ExclusionStrategy serializeExclusionStrategy;
|
||||||
static final ExclusionStrategy EXCLUDE_INNER_CLASSES = new ExclusionStrategy() {
|
private ExclusionStrategy deserializeExclusionStrategy;
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;
|
||||||
return isInnerClass(f.getDeclaredClass());
|
private double ignoreVersionsAfter = GsonExclusionStrategy.IGNORE_VERSIONS;
|
||||||
}
|
private boolean serializeInnerClasses = true;
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
private boolean excludeFieldsWithoutExposeAnnotation = false;
|
||||||
return isInnerClass(clazz);
|
|
||||||
}
|
|
||||||
private boolean isInnerClass(Class<?> clazz) {
|
|
||||||
return clazz.isMemberClass() && !isStatic(clazz);
|
|
||||||
}
|
|
||||||
private boolean isStatic(Class<?> clazz) {
|
|
||||||
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Excludes fields that do not have the {@link Expose} annotation */
|
|
||||||
static final ExclusionStrategy REQUIRE_EXPOSE_DESERIALIZE = new ExclusionStrategy() {
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
Expose annotation = f.getAnnotation(Expose.class);
|
|
||||||
return annotation == null || !annotation.deserialize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Excludes fields that do not have the {@link Expose} annotation */
|
|
||||||
static final ExclusionStrategy REQUIRE_EXPOSE_SERIALIZE = new ExclusionStrategy() {
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
Expose annotation = f.getAnnotation(Expose.class);
|
|
||||||
return annotation == null || !annotation.serialize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static final ExclusionStrategy EXCLUDE_ANONYMOUS_AND_LOCAL = new ExclusionStrategy() {
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
return isAnonymousOrLocal(f.getDeclaredClass());
|
|
||||||
}
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return isAnonymousOrLocal(clazz);
|
|
||||||
}
|
|
||||||
private boolean isAnonymousOrLocal(Class<?> clazz) {
|
|
||||||
return !Enum.class.isAssignableFrom(clazz)
|
|
||||||
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static final ExclusionStrategy EXCLUDE_SYNTHETIC_FIELDS = new ExclusionStrategy() {
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
return f.isSynthetic();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static final ModifierBasedExclusionStrategy EXCLUDE_TRANSIENT_AND_STATIC
|
|
||||||
= new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC);
|
|
||||||
|
|
||||||
private final Set<ExclusionStrategy> serializeExclusionStrategies =
|
|
||||||
new HashSet<ExclusionStrategy>();
|
|
||||||
private final Set<ExclusionStrategy> deserializeExclusionStrategies =
|
|
||||||
new HashSet<ExclusionStrategy>();
|
|
||||||
|
|
||||||
private double ignoreVersionsAfter;
|
|
||||||
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
|
|
||||||
private boolean serializeInnerClasses;
|
|
||||||
private boolean excludeFieldsWithoutExposeAnnotation;
|
|
||||||
private LongSerializationPolicy longSerializationPolicy;
|
private LongSerializationPolicy longSerializationPolicy;
|
||||||
private FieldNamingStrategy fieldNamingPolicy;
|
private FieldNamingStrategy fieldNamingPolicy;
|
||||||
private final TypeMap<InstanceCreator<?>> instanceCreators;
|
private final TypeMap<InstanceCreator<?>> instanceCreators;
|
||||||
@ -164,19 +94,9 @@ public final class GsonBuilder {
|
|||||||
* {@link #create()}.
|
* {@link #create()}.
|
||||||
*/
|
*/
|
||||||
public GsonBuilder() {
|
public GsonBuilder() {
|
||||||
// add default exclusion strategies
|
|
||||||
deserializeExclusionStrategies.add(EXCLUDE_ANONYMOUS_AND_LOCAL);
|
|
||||||
deserializeExclusionStrategies.add(EXCLUDE_SYNTHETIC_FIELDS);
|
|
||||||
serializeExclusionStrategies.add(EXCLUDE_ANONYMOUS_AND_LOCAL);
|
|
||||||
serializeExclusionStrategies.add(EXCLUDE_SYNTHETIC_FIELDS);
|
|
||||||
|
|
||||||
// setup default values
|
// setup default values
|
||||||
ignoreVersionsAfter = VersionExclusionStrategy.IGNORE_VERSIONS;
|
|
||||||
serializeInnerClasses = true;
|
|
||||||
prettyPrinting = false;
|
prettyPrinting = false;
|
||||||
escapeHtmlChars = true;
|
escapeHtmlChars = true;
|
||||||
modifierBasedExclusionStrategy = EXCLUDE_TRANSIENT_AND_STATIC;
|
|
||||||
excludeFieldsWithoutExposeAnnotation = false;
|
|
||||||
longSerializationPolicy = LongSerializationPolicy.DEFAULT;
|
longSerializationPolicy = LongSerializationPolicy.DEFAULT;
|
||||||
fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
|
fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
|
||||||
instanceCreators = new TypeMap<InstanceCreator<?>>();
|
instanceCreators = new TypeMap<InstanceCreator<?>>();
|
||||||
@ -238,7 +158,10 @@ public final class GsonBuilder {
|
|||||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||||
*/
|
*/
|
||||||
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
|
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
|
||||||
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
|
this.modifiers = 0;
|
||||||
|
for (int modifier : modifiers) {
|
||||||
|
this.modifiers |= modifier;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,9 +344,10 @@ public final class GsonBuilder {
|
|||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
|
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
|
||||||
List<ExclusionStrategy> strategyList = Arrays.asList(strategies);
|
for (ExclusionStrategy strategy : strategies) {
|
||||||
serializeExclusionStrategies.addAll(strategyList);
|
addSerializationExclusionStrategy(strategy);
|
||||||
deserializeExclusionStrategies.addAll(strategyList);
|
addDeserializationExclusionStrategy(strategy);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +364,7 @@ public final class GsonBuilder {
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
|
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
|
||||||
serializeExclusionStrategies.add(strategy);
|
serializeExclusionStrategy = combine(serializeExclusionStrategy, strategy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +381,7 @@ public final class GsonBuilder {
|
|||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
|
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
|
||||||
deserializeExclusionStrategies.add(strategy);
|
deserializeExclusionStrategy = combine(deserializeExclusionStrategy, strategy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,6 +600,27 @@ public final class GsonBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unions two exclusion strategies. If the first is null, this returns the
|
||||||
|
* second.
|
||||||
|
*/
|
||||||
|
private static ExclusionStrategy combine(final ExclusionStrategy a, final ExclusionStrategy b) {
|
||||||
|
if (b == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
if (a == null) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return new ExclusionStrategy() {
|
||||||
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
return a.shouldSkipField(f) || b.shouldSkipField(f);
|
||||||
|
}
|
||||||
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
return a.shouldSkipClass(clazz) || b.shouldSkipClass(clazz);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link Gson} instance based on the current configuration. This method is free of
|
* Creates a {@link Gson} instance based on the current configuration. This method is free of
|
||||||
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
|
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
|
||||||
@ -683,32 +628,17 @@ public final class GsonBuilder {
|
|||||||
* @return an instance of Gson configured with the options currently set in this builder
|
* @return an instance of Gson configured with the options currently set in this builder
|
||||||
*/
|
*/
|
||||||
public Gson create() {
|
public Gson create() {
|
||||||
List<ExclusionStrategy> deserializationStrategies =
|
|
||||||
new LinkedList<ExclusionStrategy>(deserializeExclusionStrategies);
|
|
||||||
List<ExclusionStrategy> serializationStrategies =
|
|
||||||
new LinkedList<ExclusionStrategy>(serializeExclusionStrategies);
|
|
||||||
deserializationStrategies.add(modifierBasedExclusionStrategy);
|
|
||||||
serializationStrategies.add(modifierBasedExclusionStrategy);
|
|
||||||
|
|
||||||
if (!serializeInnerClasses) {
|
|
||||||
deserializationStrategies.add(EXCLUDE_INNER_CLASSES);
|
|
||||||
serializationStrategies.add(EXCLUDE_INNER_CLASSES);
|
|
||||||
}
|
|
||||||
if (ignoreVersionsAfter != VersionExclusionStrategy.IGNORE_VERSIONS) {
|
|
||||||
VersionExclusionStrategy versionExclusionStrategy =
|
|
||||||
new VersionExclusionStrategy(ignoreVersionsAfter);
|
|
||||||
deserializationStrategies.add(versionExclusionStrategy);
|
|
||||||
serializationStrategies.add(versionExclusionStrategy);
|
|
||||||
}
|
|
||||||
if (excludeFieldsWithoutExposeAnnotation) {
|
|
||||||
deserializationStrategies.add(REQUIRE_EXPOSE_DESERIALIZE);
|
|
||||||
serializationStrategies.add(REQUIRE_EXPOSE_SERIALIZE);
|
|
||||||
}
|
|
||||||
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, serializers, deserializers);
|
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, serializers, deserializers);
|
||||||
|
|
||||||
return new Gson(new DisjunctionExclusionStrategy(deserializationStrategies),
|
ExclusionStrategy deserializeExclusionStrategy = combine(this.deserializeExclusionStrategy,
|
||||||
new DisjunctionExclusionStrategy(serializationStrategies),
|
new GsonExclusionStrategy(ignoreVersionsAfter, modifiers, true,
|
||||||
fieldNamingPolicy, instanceCreators.copyOf().makeUnmodifiable(), serializeNulls,
|
true, serializeInnerClasses, false, excludeFieldsWithoutExposeAnnotation));
|
||||||
|
ExclusionStrategy serializeExclusionStrategy = combine(this.serializeExclusionStrategy,
|
||||||
|
new GsonExclusionStrategy(ignoreVersionsAfter, modifiers, true, true,
|
||||||
|
serializeInnerClasses, excludeFieldsWithoutExposeAnnotation, false));
|
||||||
|
|
||||||
|
return new Gson(deserializeExclusionStrategy, serializeExclusionStrategy, fieldNamingPolicy,
|
||||||
|
instanceCreators.copyOf().makeUnmodifiable(), serializeNulls,
|
||||||
serializers.copyOf().makeUnmodifiable(), deserializers.copyOf().makeUnmodifiable(),
|
serializers.copyOf().makeUnmodifiable(), deserializers.copyOf().makeUnmodifiable(),
|
||||||
complexMapKeySerialization, generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
|
complexMapKeySerialization, generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
|
||||||
serializeSpecialFloatingPointValues, longSerializationPolicy, typeAdapterFactories);
|
serializeSpecialFloatingPointValues, longSerializationPolicy, typeAdapterFactories);
|
||||||
|
132
gson/src/main/java/com/google/gson/GsonExclusionStrategy.java
Normal file
132
gson/src/main/java/com/google/gson/GsonExclusionStrategy.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.Since;
|
||||||
|
import com.google.gson.annotations.Until;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A configurable exclusion strategy. This strategy supports version attributes
|
||||||
|
* {@link Since} and {@link Until}, modifiers, synthetic fields, anonymous and
|
||||||
|
* local classes, inner classes, and fields with the {@link Expose} annotation.
|
||||||
|
*
|
||||||
|
* @author Joel Leitch
|
||||||
|
* @author Jesse Wilson
|
||||||
|
*/
|
||||||
|
final class GsonExclusionStrategy implements ExclusionStrategy {
|
||||||
|
static final double IGNORE_VERSIONS = -1D;
|
||||||
|
private final double version;
|
||||||
|
private final int modifiers;
|
||||||
|
private final boolean excludeSyntheticFields;
|
||||||
|
private final boolean excludeAnonymousAndLocal;
|
||||||
|
private final boolean serializeInnerClasses;
|
||||||
|
private final boolean requireExposeOnSerialize;
|
||||||
|
private final boolean requireExposeOnDeserialize;
|
||||||
|
|
||||||
|
GsonExclusionStrategy(double version, int modifiers, boolean excludeSyntheticFields,
|
||||||
|
boolean excludeAnonymousAndLocal, boolean serializeInnerClasses,
|
||||||
|
boolean requireExposeOnSerialize, boolean requireExposeOnDeserialize) {
|
||||||
|
this.version = version;
|
||||||
|
this.modifiers = modifiers;
|
||||||
|
this.excludeSyntheticFields = excludeSyntheticFields;
|
||||||
|
this.excludeAnonymousAndLocal = excludeAnonymousAndLocal;
|
||||||
|
this.serializeInnerClasses = serializeInnerClasses;
|
||||||
|
this.requireExposeOnSerialize = requireExposeOnSerialize;
|
||||||
|
this.requireExposeOnDeserialize = requireExposeOnDeserialize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
if (f.hasModifier(modifiers)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (version != GsonExclusionStrategy.IGNORE_VERSIONS
|
||||||
|
&& !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (excludeSyntheticFields && f.isSynthetic()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (requireExposeOnSerialize || requireExposeOnDeserialize) {
|
||||||
|
Expose annotation = f.getAnnotation(Expose.class);
|
||||||
|
if (annotation == null
|
||||||
|
|| requireExposeOnSerialize && !annotation.serialize()
|
||||||
|
|| requireExposeOnDeserialize && !annotation.deserialize()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!serializeInnerClasses && isInnerClass(f.getDeclaredClass())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (excludeAnonymousAndLocal && isAnonymousOrLocal(f.getDeclaredClass())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
if (version != GsonExclusionStrategy.IGNORE_VERSIONS
|
||||||
|
&& !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!serializeInnerClasses && isInnerClass(clazz)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (excludeAnonymousAndLocal && isAnonymousOrLocal(clazz)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAnonymousOrLocal(Class<?> clazz) {
|
||||||
|
return !Enum.class.isAssignableFrom(clazz)
|
||||||
|
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInnerClass(Class<?> clazz) {
|
||||||
|
return clazz.isMemberClass() && !isStatic(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStatic(Class<?> clazz) {
|
||||||
|
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidVersion(Since since, Until until) {
|
||||||
|
return isValidSince(since) && isValidUntil(until);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidSince(Since annotation) {
|
||||||
|
if (annotation != null) {
|
||||||
|
double annotationVersion = annotation.value();
|
||||||
|
if (annotationVersion > version) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidUntil(Until annotation) {
|
||||||
|
if (annotation != null) {
|
||||||
|
double annotationVersion = annotation.value();
|
||||||
|
if (annotationVersion <= version) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,53 +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.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exclude fields based on particular field modifiers. For a list of possible
|
|
||||||
* modifiers, see {@link java.lang.reflect.Modifier}.
|
|
||||||
*
|
|
||||||
* @author Inderjeet Singh
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
|
|
||||||
private final Collection<Integer> modifiers;
|
|
||||||
|
|
||||||
public ModifierBasedExclusionStrategy(int... modifiers) {
|
|
||||||
this.modifiers = new HashSet<Integer>();
|
|
||||||
if (modifiers != null) {
|
|
||||||
for (int modifier : modifiers) {
|
|
||||||
this.modifiers.add(modifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
for (int modifier : modifiers) {
|
|
||||||
if (f.hasModifier(modifier)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +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 com.google.gson.annotations.Since;
|
|
||||||
import com.google.gson.annotations.Until;
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This strategy will exclude any files and/or class that are passed the
|
|
||||||
* {@link #version} value.
|
|
||||||
*
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
final class VersionExclusionStrategy implements ExclusionStrategy {
|
|
||||||
static final double IGNORE_VERSIONS = -1D;
|
|
||||||
private final double version;
|
|
||||||
|
|
||||||
VersionExclusionStrategy(double version) {
|
|
||||||
$Gson$Preconditions.checkArgument(version >= 0.0D);
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipField(FieldAttributes f) {
|
|
||||||
return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSkipClass(Class<?> clazz) {
|
|
||||||
return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidVersion(Since since, Until until) {
|
|
||||||
return (isValidSince(since) && isValidUntil(until));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidSince(Since annotation) {
|
|
||||||
if (annotation != null) {
|
|
||||||
double annotationVersion = annotation.value();
|
|
||||||
if (annotationVersion > version) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidUntil(Until annotation) {
|
|
||||||
if (annotation != null) {
|
|
||||||
double annotationVersion = annotation.value();
|
|
||||||
if (annotationVersion <= version) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +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 junit.framework.TestCase;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for the {@link DisjunctionExclusionStrategy} class.
|
|
||||||
*
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
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 Class<?> CLAZZ = String.class;
|
|
||||||
private static final FieldAttributes FIELD =
|
|
||||||
new FieldAttributes(CLAZZ.getFields()[0]);
|
|
||||||
|
|
||||||
public void testBadInstantiation() throws Exception {
|
|
||||||
try {
|
|
||||||
List<ExclusionStrategy> constructorParam = null;
|
|
||||||
new DisjunctionExclusionStrategy(constructorParam);
|
|
||||||
fail("Should throw an exception");
|
|
||||||
} catch (NullPointerException expected) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSkipFieldsWithMixedTrueAndFalse() throws Exception {
|
|
||||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
|
||||||
strategies.add(FALSE_STRATEGY);
|
|
||||||
strategies.add(TRUE_STRATEGY);
|
|
||||||
DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies);
|
|
||||||
|
|
||||||
assertTrue(strategy.shouldSkipClass(CLAZZ));
|
|
||||||
assertTrue(strategy.shouldSkipField(FIELD));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSkipFieldsWithFalseOnly() throws Exception {
|
|
||||||
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
|
||||||
strategies.add(FALSE_STRATEGY);
|
|
||||||
DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies);
|
|
||||||
|
|
||||||
assertFalse(strategy.shouldSkipClass(CLAZZ));
|
|
||||||
assertFalse(strategy.shouldSkipField(FIELD));
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,8 +28,10 @@ import java.lang.reflect.Field;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public class ExposeAnnotationExclusionStrategyTest extends TestCase {
|
public class ExposeAnnotationExclusionStrategyTest extends TestCase {
|
||||||
private ExclusionStrategy deserializationStrategy = GsonBuilder.REQUIRE_EXPOSE_DESERIALIZE;
|
private ExclusionStrategy serializationStrategy = new GsonExclusionStrategy(
|
||||||
private ExclusionStrategy serializationStrategy = GsonBuilder.REQUIRE_EXPOSE_SERIALIZE;
|
GsonExclusionStrategy.IGNORE_VERSIONS, 0, true, true, true, true, false);
|
||||||
|
private ExclusionStrategy deserializationStrategy = new GsonExclusionStrategy(
|
||||||
|
GsonExclusionStrategy.IGNORE_VERSIONS, 0, true, true, true, false, true);
|
||||||
|
|
||||||
public void testNeverSkipClasses() throws Exception {
|
public void testNeverSkipClasses() throws Exception {
|
||||||
assertFalse(deserializationStrategy.shouldSkipClass(MockObject.class));
|
assertFalse(deserializationStrategy.shouldSkipClass(MockObject.class));
|
||||||
|
@ -19,7 +19,6 @@ package com.google.gson;
|
|||||||
import com.google.gson.common.TestTypes.ClassWithNoFields;
|
import com.google.gson.common.TestTypes.ClassWithNoFields;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,10 +33,9 @@ public class FunctionWithInternalDependenciesTest extends TestCase {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testAnonymousLocalClassesSerialization() throws Exception {
|
public void testAnonymousLocalClassesSerialization() throws Exception {
|
||||||
LinkedList<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
|
ExclusionStrategy exclusionStrategy = new GsonExclusionStrategy(
|
||||||
strategies.add(GsonBuilder.EXCLUDE_SYNTHETIC_FIELDS);
|
GsonExclusionStrategy.IGNORE_VERSIONS, Modifier.TRANSIENT | Modifier.STATIC,
|
||||||
strategies.add(new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC));
|
true, false, true, false, false);
|
||||||
ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies);
|
|
||||||
Gson gson = new Gson(exclusionStrategy, exclusionStrategy, FieldNamingPolicy.IDENTITY,
|
Gson gson = new Gson(exclusionStrategy, exclusionStrategy, FieldNamingPolicy.IDENTITY,
|
||||||
Gson.EMPTY_MAP, false, Gson.EMPTY_MAP, Gson.EMPTY_MAP, false,
|
Gson.EMPTY_MAP, false, Gson.EMPTY_MAP, Gson.EMPTY_MAP, false,
|
||||||
Gson.DEFAULT_JSON_NON_EXECUTABLE,
|
Gson.DEFAULT_JSON_NON_EXECUTABLE,
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for GsonBuilder.EXCLUDE_INNER_CLASSES.
|
* Unit test for GsonBuilder.EXCLUDE_INNER_CLASSES.
|
||||||
@ -26,18 +25,10 @@ import java.lang.reflect.Field;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public class InnerClassExclusionStrategyTest extends TestCase {
|
public class InnerClassExclusionStrategyTest extends TestCase {
|
||||||
public InnerClass innerClass;
|
public InnerClass innerClass = new InnerClass();
|
||||||
public StaticNestedClass staticNestedClass;
|
public StaticNestedClass staticNestedClass = new StaticNestedClass();
|
||||||
|
private ExclusionStrategy strategy = new GsonExclusionStrategy(
|
||||||
private ExclusionStrategy strategy;
|
GsonExclusionStrategy.IGNORE_VERSIONS, 0, true, false, false, false, false);
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
innerClass = new InnerClass();
|
|
||||||
staticNestedClass = new StaticNestedClass();
|
|
||||||
strategy = GsonBuilder.EXCLUDE_INNER_CLASSES;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testExcludeInnerClassObject() throws Exception {
|
public void testExcludeInnerClassObject() throws Exception {
|
||||||
Class<?> clazz = innerClass.getClass();
|
Class<?> clazz = innerClass.getClass();
|
||||||
|
@ -16,31 +16,23 @@
|
|||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Since;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import com.google.gson.annotations.Since;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the {@link VersionExclusionStrategy} class.
|
* Unit tests for the {@link GsonExclusionStrategy} class.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public class VersionExclusionStrategyTest extends TestCase {
|
public class VersionExclusionStrategyTest extends TestCase {
|
||||||
private static final double VERSION = 5.0D;
|
private static final double VERSION = 5.0D;
|
||||||
|
|
||||||
public void testDisallowNegativeValuesAndFailFast() throws Exception {
|
|
||||||
try {
|
|
||||||
new VersionExclusionStrategy(-1.0D);
|
|
||||||
fail("should have thrown an exception.");
|
|
||||||
} catch (IllegalArgumentException expected) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testClassAndFieldAreAtSameVersion() throws Exception {
|
public void testClassAndFieldAreAtSameVersion() throws Exception {
|
||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
Field f = clazz.getField("someField");
|
Field f = clazz.getField("someField");
|
||||||
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION);
|
GsonExclusionStrategy strategy = new GsonExclusionStrategy(VERSION, 0,
|
||||||
|
true, true, true, false, false);
|
||||||
assertFalse(strategy.shouldSkipClass(clazz));
|
assertFalse(strategy.shouldSkipClass(clazz));
|
||||||
|
|
||||||
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
||||||
@ -50,7 +42,8 @@ public class VersionExclusionStrategyTest extends TestCase {
|
|||||||
public void testClassAndFieldAreBehindInVersion() throws Exception {
|
public void testClassAndFieldAreBehindInVersion() throws Exception {
|
||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
Field f = clazz.getField("someField");
|
Field f = clazz.getField("someField");
|
||||||
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION + 1);
|
GsonExclusionStrategy strategy = new GsonExclusionStrategy(VERSION + 1, 0,
|
||||||
|
true, true, true, false, false);
|
||||||
assertFalse(strategy.shouldSkipClass(clazz));
|
assertFalse(strategy.shouldSkipClass(clazz));
|
||||||
|
|
||||||
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
||||||
@ -60,7 +53,8 @@ public class VersionExclusionStrategyTest extends TestCase {
|
|||||||
public void testClassAndFieldAreAheadInVersion() throws Exception {
|
public void testClassAndFieldAreAheadInVersion() throws Exception {
|
||||||
Class<MockObject> clazz = MockObject.class;
|
Class<MockObject> clazz = MockObject.class;
|
||||||
Field f = clazz.getField("someField");
|
Field f = clazz.getField("someField");
|
||||||
VersionExclusionStrategy strategy = new VersionExclusionStrategy(VERSION - 1);
|
GsonExclusionStrategy strategy = new GsonExclusionStrategy(VERSION - 1, 0,
|
||||||
|
true, true, true, false, false);
|
||||||
assertTrue(strategy.shouldSkipClass(clazz));
|
assertTrue(strategy.shouldSkipClass(clazz));
|
||||||
|
|
||||||
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
||||||
|
Loading…
Reference in New Issue
Block a user