3

我在我的持久对象上使用 Gson 自定义序列化。同时,我也在使用序列化排除策略。代码如下所示:

public class GsonFactory {

    public static Gson build(Type type, final List<String> fieldExclusions,
            final List<Class<?>> classExclusions) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {
            public boolean shouldSkipField(FieldAttributes f) {
                return fieldExclusions == null ? false : fieldExclusions
                        .contains(f.getName());
            }

            public boolean shouldSkipClass(Class<?> clazz) {
                return classExclusions == null ? false : classExclusions
                        .contains(clazz);
            }
        });
        // Uncommenting this line will produce error
        // gsonBuilder.registerTypeAdapter(type,
        // new PersistentObjectJsonSerializer());
        return gsonBuilder.create();
    }
}

class PersistentObjectJsonSerializer implements
        JsonSerializer<PersistentObject> {

    public JsonElement serialize(PersistentObject src, Type typeOfSrc,
            JsonSerializationContext context) {
        src.setDT_RowId(src.getId());
        Gson gson = new Gson();
        return gson.toJsonTree(src);
    }

}

但是,如果我取消注释gsonBuilder.registerTypeAdapter(type, new PersistentObjectJsonSerializer());, 在创建时gsonBuilder将给出以下错误:

java.lang.StackOverflowError
    com.google.gson.reflect.TypeToken.equals(TypeToken.java:284)
    java.util.HashMap.get(HashMap.java:305)
    java.util.Collections$SynchronizedMap.get(Collections.java:1979)
    com.google.gson.Gson.getAdapter(Gson.java:337)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:883)

我的 PersistentObject java 类:

@MappedSuperclass
public abstract class PersistentObject implements Serializable {

....

@Transient
protected long DT_RowId;
// getters, setters not shown

...

}

这就是我在 GenericHibernateDAO 中调用 GsonFactory.build 的方式:

public abstract class GenericHibernateDAO<T, ID extends Serializable> {

private Class<T> persistentClass;

@SuppressWarnings("unchecked")
public GenericHibernateDAO() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
            .getGenericSuperclass()).getActualTypeArguments()[0];
}


public String listAsJsonResponse(){
    ...
    // testing start
    List<Class<?>> classExclusions = new ArrayList<Class<?>>();
    classExclusions.add(Role.class);
    List<String> fieldExclusions = new ArrayList<String>();
    fieldExclusions.add("users");
    fieldExclusions.add("password");
    Gson gson = GsonFactory.build(persistentClass,fieldExclusions, null);
    ...
    return jsonResponse.toString();
}
}

这里persistentClass指的是User类:

@Repository
public class UserDAO extends GenericHibernateDAO<User, Long> {

}

基本上我无法同时使用这两个功能。关于可能导致此问题的任何指针?

4

2 回答 2

3

这是一个老问题,但也许我的回答仍然可以帮助某人。

您在序列化程序中创建一个新的 Gson 对象。这个 Gson 对象不再知道 PersistentObjects 的 ExclusionStrategies。如果您的 PersistantObject 具有将再次导致 PersistentObject 的属性对象(在您的情况下,用户可能具有 persistantObject 的属性),那么您将陷入无限循环并进入 stackoverflow 异常。

一种解决方案是再次向序列化程序中的 gson 对象添加排除策略。但是不要再将序列化程序添加到这个 gson 对象中!

class PersistentObjectJsonSerializer implements
    JsonSerializer<PersistentObject> {

    public JsonElement serialize(PersistentObject src, Type typeOfSrc,
        JsonSerializationContext context) {
        src.setDT_RowId(src.getId());
        Gson gson = new Gson();
        //add exclusion strategy here again
        return gson.toJsonTree(src);
    }

}
于 2013-05-27T12:31:51.993 回答
0

Gson 是开源的,您可以获取源代码。为什么不这样做并按照代码查看它在哪一点引发异常?似乎 gson 陷入了无限循环。确实,gson 大量使用递归。如果它实际上是一个错误,您可以将它报告给 Gson 人员,他们将在下一个版本中解决它。

http://code.google.com/p/google-gson/issues/list

于 2012-11-16T09:06:25.490 回答