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)

私のPersistentObjectJavaクラス:

@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 例外が発生します。

1 つの解決策は、シリアライザーの 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 に答える