From 3331dcdab08792f6281ab6343532031a52f54003 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Wed, 3 Aug 2011 00:47:36 +0000 Subject: [PATCH] Using serializationExclusionStrategy while navigating through fields to decide which ones to skip. --- gson/src/main/java/com/google/gson/Gson.java | 33 +++++--- .../internal/bind/ReflectiveTypeAdapter.java | 81 ++++++++++--------- 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 79f34eef..9e411b41 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -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(); } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java index 353ff975..e4907b4c 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapter.java @@ -31,42 +31,8 @@ import java.util.Map; /** * Adapts the fields of an object to the properties of a JSON object. */ -final class ReflectiveTypeAdapter extends TypeAdapter { - public static final Factory FACTORY = new Factory() { - public TypeAdapter create(MiniGson context, TypeToken type) { - Class raw = type.getRawType(); - - if (!Object.class.isAssignableFrom(raw)) { - return null; // it's a primitive! - } - - // TODO: use Joel's constructor calling code (with setAccessible) - Constructor constructor; - try { - constructor = raw.getDeclaredConstructor(); - } catch (NoSuchMethodException e) { - return null; - } - - return new ReflectiveTypeAdapter(constructor, getBoundFields(context, type, raw)); - } - - private Map getBoundFields( - MiniGson context, TypeToken type, Class raw) { - Map result = new LinkedHashMap(); - 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 extends TypeAdapter { + public static final Factory FACTORY = new FactoryImpl(); private final Constructor constructor; private final Map map; @@ -145,6 +111,49 @@ final class ReflectiveTypeAdapter extends TypeAdapter { }; } + public static class FactoryImpl implements Factory { + public boolean skipField(Class declaringClazz, Field f, Type declaringType) { + return false; + } + public TypeAdapter create(MiniGson context, TypeToken type) { + Class raw = type.getRawType(); + + if (!Object.class.isAssignableFrom(raw)) { + return null; // it's a primitive! + } + + // TODO: use Joel's constructor calling code (with setAccessible) + Constructor constructor; + try { + constructor = raw.getDeclaredConstructor(); + } catch (NoSuchMethodException e) { + return null; + } + + return new ReflectiveTypeAdapter(constructor, getBoundFields(context, type, raw)); + } + + private Map getBoundFields( + MiniGson context, TypeToken type, Class raw) { + Map result = new LinkedHashMap(); + 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;