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;
|
||||
|
||||
/**
|
||||
* A strategy pattern (see "Design Patterns" written by GoF for some literature on this pattern)
|
||||
* 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.
|
||||
* 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 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
|
||||
* type will be excluded from the output.
|
||||
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
||||
*
|
||||
* <p><pre class="code">
|
||||
* private static class UserDefinedExclusionStrategy implements ExclusionStrategy {
|
||||
* <p><strong>Exclude fields and objects based on a particular class type:<strong>
|
||||
* <pre class="code">
|
||||
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
||||
* private final Class<?> excludedThisClass;
|
||||
*
|
||||
* UserDefinedExclusionStrategy(Class<?> excludedThisClass) {
|
||||
* public pecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
||||
* this.excludedThisClass = excludedThisClass;
|
||||
* }
|
||||
*
|
||||
@ -40,7 +42,29 @@ package com.google.gson;
|
||||
* 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);
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .setExclusionStrategies(excludeStrings)
|
||||
|
@ -115,8 +115,9 @@ final class FieldAttributes {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is exposed internally only for the
|
||||
* @return
|
||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||
*
|
||||
* @return true if the field is synthetic; otherwise false
|
||||
*/
|
||||
boolean isSynthetic() {
|
||||
return field.isSynthetic();
|
||||
|
@ -93,6 +93,10 @@ final class ObjectNavigator {
|
||||
* If a field is null, it does not get visited.
|
||||
*/
|
||||
public void accept(Visitor visitor) {
|
||||
TypeInfo objTypeInfo = new TypeInfo(objTypePair.getType());
|
||||
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
||||
return;
|
||||
}
|
||||
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
|
||||
if (!visitedWithCustomHandler) {
|
||||
Object obj = objTypePair.getObject();
|
||||
@ -100,10 +104,7 @@ final class ObjectNavigator {
|
||||
if (objectToVisit == null) {
|
||||
return;
|
||||
}
|
||||
TypeInfo objTypeInfo = new TypeInfo(objTypePair.getType());
|
||||
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
|
||||
return;
|
||||
}
|
||||
|
||||
visitor.start(objTypePair);
|
||||
try {
|
||||
if (objTypeInfo.isArray()) {
|
||||
@ -141,7 +142,9 @@ final class ObjectNavigator {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
AccessibleObject.setAccessible(fields, true);
|
||||
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
|
||||
} else {
|
||||
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");
|
||||
* 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 {
|
||||
assertFalse(strategy.shouldSkipField(
|
||||
new FieldAttributes("".getClass().getFields()[0])));
|
||||
new FieldAttributes(String.class.getFields()[0])));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user