[英]Gson exclusion strategy and custom serialization
我在我的持久對象上使用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> {
}
基本上我無法同時使用這兩個功能。 任何可能導致此問題的指針?
這是一個老問題,但也許我的答案仍然可以幫助某人。
您在序列化程序中創建一個新的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);
}
}
Gson是開源的,你可以獲得源代碼。 為什么不這樣做並按照代碼查看它拋出異常的哪一點? 似乎gson陷入無限循環。 確實,gson經常使用遞歸。 如果它實際上是一個錯誤,你可以向Gson人報告,他們將在下一個版本中解決它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.