Addresses comments in r481 (except for the interface change....leaving FieldAttributes as a class).
Change the exclusion order in ObjectNavigator to exclude a top-level class (if exclusion strategy suggests class should be skipped) even if it is marked with a custom (de)serializer.
This commit is contained in:
parent
e9c156b016
commit
dc5922e703
@ -17,18 +17,20 @@
|
|||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy pattern (see "Design Patterns" written by GoF for some literature on this pattern)
|
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
|
||||||
* definition that is used to decide whether or not a field or top-level class should be serialized
|
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
|
||||||
* (or deserialized) as part of the JSON output/input.
|
* if the {@link this#shouldSkipClass(Class)} method returns false then that class or field type
|
||||||
|
* will not be part of the JSON output. For deserialization, if {@link this#shouldSkipClass(Class)}
|
||||||
|
* returns false, then it will not be set as part of the Java object structure.
|
||||||
*
|
*
|
||||||
* <p>The following example show an implementation of an {@code ExclusionStrategy} where a specific
|
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
||||||
* type will be excluded from the output.
|
|
||||||
*
|
*
|
||||||
* <p><pre class="code">
|
* <p><strong>Exclude fields and objects based on a particular class type:<strong>
|
||||||
* private static class UserDefinedExclusionStrategy implements ExclusionStrategy {
|
* <pre class="code">
|
||||||
|
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
||||||
* private final Class<?> excludedThisClass;
|
* private final Class<?> excludedThisClass;
|
||||||
*
|
*
|
||||||
* UserDefinedExclusionStrategy(Class<?> excludedThisClass) {
|
* public pecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
||||||
* this.excludedThisClass = excludedThisClass;
|
* this.excludedThisClass = excludedThisClass;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
@ -40,7 +42,29 @@ package com.google.gson;
|
|||||||
* return excludedThisClass.equals(f.getDeclaredClass());
|
* return excludedThisClass.equals(f.getDeclaredClass());
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
|
||||||
|
* <pre class="code">
|
||||||
|
* public @interface FooAnnotation {
|
||||||
|
* // some implementation here
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Excludes any field (or class) that is tagged with an "@FooAnnotation"
|
||||||
|
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
|
||||||
|
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
|
* return clazz.getAnnotation(FooAnnotation.class) != null;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public boolean shouldSkipField(FieldAttributes f) {
|
||||||
|
* return f.getAnnotation(FooAnnotation.class) != null;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </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
|
||||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||||
* Gson gson = new GsonBuilder()
|
* Gson gson = new GsonBuilder()
|
||||||
* .setExclusionStrategies(excludeStrings)
|
* .setExclusionStrategies(excludeStrings)
|
||||||
|
@ -115,8 +115,9 @@ final class FieldAttributes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is exposed internally only for the
|
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||||
* @return
|
*
|
||||||
|
* @return true if the field is synthetic; otherwise false
|
||||||
*/
|
*/
|
||||||
boolean isSynthetic() {
|
boolean isSynthetic() {
|
||||||
return field.isSynthetic();
|
return field.isSynthetic();
|
||||||
|
@ -93,6 +93,10 @@ final class ObjectNavigator {
|
|||||||
* If a field is null, it does not get visited.
|
* If a field is null, it does not get visited.
|
||||||
*/
|
*/
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
|
TypeInfo objTypeInfo = new TypeInfo(objTypePair.getType());
|
||||||
|
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
|
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
|
||||||
if (!visitedWithCustomHandler) {
|
if (!visitedWithCustomHandler) {
|
||||||
Object obj = objTypePair.getObject();
|
Object obj = objTypePair.getObject();
|
||||||
@ -100,10 +104,7 @@ final class ObjectNavigator {
|
|||||||
if (objectToVisit == null) {
|
if (objectToVisit == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TypeInfo objTypeInfo = new TypeInfo(objTypePair.getType());
|
|
||||||
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
visitor.start(objTypePair);
|
visitor.start(objTypePair);
|
||||||
try {
|
try {
|
||||||
if (objTypeInfo.isArray()) {
|
if (objTypeInfo.isArray()) {
|
||||||
@ -141,7 +142,9 @@ final class ObjectNavigator {
|
|||||||
Field[] fields = clazz.getDeclaredFields();
|
Field[] fields = clazz.getDeclaredFields();
|
||||||
AccessibleObject.setAccessible(fields, true);
|
AccessibleObject.setAccessible(fields, true);
|
||||||
for (Field f : fields) {
|
for (Field f : fields) {
|
||||||
if (exclusionStrategy.shouldSkipField(new FieldAttributes(f))) {
|
FieldAttributes fieldAttributes = new FieldAttributes(f);
|
||||||
|
if (exclusionStrategy.shouldSkipField(fieldAttributes)
|
||||||
|
|| exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
|
||||||
continue; // skip
|
continue; // skip
|
||||||
} else {
|
} else {
|
||||||
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.getType());
|
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.getType());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -38,6 +38,6 @@ public class NullExclusionStrategyTest extends TestCase {
|
|||||||
|
|
||||||
public void testNeverSkipsField() throws Exception {
|
public void testNeverSkipsField() throws Exception {
|
||||||
assertFalse(strategy.shouldSkipField(
|
assertFalse(strategy.shouldSkipField(
|
||||||
new FieldAttributes("".getClass().getFields()[0])));
|
new FieldAttributes(String.class.getFields()[0])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user