Using serializationExclusionStrategy while navigating through fields to decide which ones to skip.
This commit is contained in:
parent
37abcf3637
commit
3331dcdab0
@ -16,23 +16,26 @@
|
||||
|
||||
package com.google.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.internal.bind.MiniGson;
|
||||
import com.google.gson.internal.bind.ReflectiveTypeAdapter;
|
||||
import com.google.gson.internal.bind.TypeAdapter;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.google.gson.stream.MalformedJsonException;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is the main class for using Gson. Gson is typically used by first constructing a
|
||||
@ -180,7 +183,17 @@ public final class Gson {
|
||||
serializeNulls
|
||||
serializers
|
||||
*/
|
||||
TypeAdapter.Factory factory = new ReflectiveTypeAdapter.FactoryImpl() {
|
||||
@Override
|
||||
public boolean skipField(Class<?> declaringClazz, Field f, Type declaredType) {
|
||||
// TODO: support deserialization policy as well
|
||||
return Gson.this.serializationExclusionStrategy.shouldSkipField(
|
||||
new FieldAttributes(declaringClazz, f, declaredType));
|
||||
}
|
||||
};
|
||||
|
||||
this.miniGson = new MiniGson.Builder()
|
||||
.factory(factory)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -31,42 +31,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Adapts the fields of an object to the properties of a JSON object.
|
||||
*/
|
||||
final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
||||
public static final Factory FACTORY = new Factory() {
|
||||
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> type) {
|
||||
Class<? super T> raw = type.getRawType();
|
||||
|
||||
if (!Object.class.isAssignableFrom(raw)) {
|
||||
return null; // it's a primitive!
|
||||
}
|
||||
|
||||
// TODO: use Joel's constructor calling code (with setAccessible)
|
||||
Constructor<? super T> constructor;
|
||||
try {
|
||||
constructor = raw.getDeclaredConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ReflectiveTypeAdapter<T>(constructor, getBoundFields(context, type, raw));
|
||||
}
|
||||
|
||||
private Map<String, BoundField> getBoundFields(
|
||||
MiniGson context, TypeToken<?> type, Class<?> raw) {
|
||||
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
|
||||
while (raw != Object.class) {
|
||||
for (Field field : raw.getDeclaredFields()) {
|
||||
field.setAccessible(true); // TODO: don't call setAccessible unless necessary
|
||||
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
|
||||
BoundField boundField = createBoundField(context, field, TypeToken.get(fieldType));
|
||||
result.put(boundField.name, boundField);
|
||||
}
|
||||
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
|
||||
raw = type.getRawType();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
public final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
||||
public static final Factory FACTORY = new FactoryImpl();
|
||||
|
||||
private final Constructor<? super T> constructor;
|
||||
private final Map<String, BoundField> map;
|
||||
@ -145,6 +111,49 @@ final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
||||
};
|
||||
}
|
||||
|
||||
public static class FactoryImpl implements Factory {
|
||||
public boolean skipField(Class<?> declaringClazz, Field f, Type declaringType) {
|
||||
return false;
|
||||
}
|
||||
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> type) {
|
||||
Class<? super T> raw = type.getRawType();
|
||||
|
||||
if (!Object.class.isAssignableFrom(raw)) {
|
||||
return null; // it's a primitive!
|
||||
}
|
||||
|
||||
// TODO: use Joel's constructor calling code (with setAccessible)
|
||||
Constructor<? super T> constructor;
|
||||
try {
|
||||
constructor = raw.getDeclaredConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ReflectiveTypeAdapter<T>(constructor, getBoundFields(context, type, raw));
|
||||
}
|
||||
|
||||
private Map<String, BoundField> getBoundFields(
|
||||
MiniGson context, TypeToken<?> type, Class<?> raw) {
|
||||
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
|
||||
Type declaredType = type.getType();
|
||||
while (raw != Object.class) {
|
||||
for (Field field : raw.getDeclaredFields()) {
|
||||
if (skipField(raw, field, declaredType)) {
|
||||
continue;
|
||||
}
|
||||
field.setAccessible(true); // TODO: don't call setAccessible unless necessary
|
||||
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
|
||||
BoundField boundField = createBoundField(context, field, TypeToken.get(fieldType));
|
||||
result.put(boundField.name, boundField);
|
||||
}
|
||||
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
|
||||
raw = type.getRawType();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class BoundField {
|
||||
final String name;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user