Стратегия исключения Gson и пользовательская сериализация
Я использую пользовательскую сериализацию 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.StackruError
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)
Мой java-класс PersistentObject:
@MappedSuperclass
public abstract class PersistentObject implements Serializable {
....
@Transient
protected long DT_RowId;
// getters, setters not shown
...
}
Вот как я называю GsonFactory.build в GenericHibernateDAO:
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> {
}
В принципе, я не могу использовать обе функции одновременно. Любой указатель на то, что может вызвать эту проблему?
2 ответа
Это старый вопрос, но, возможно, мой ответ все еще может кому-то помочь.
Вы создаете новый объект Gson в вашем сериализаторе. Этот объект Gson больше не знает ваши ExclusionStrategies для объектов PersistentObject. Если ваш PersistantObject имеет объекты атрибутов, которые снова приведут к PersistentObject (в вашем случае у пользователей могут быть атрибуты persistantObject), вы попадете в бесконечный цикл и в исключение stackru.
Одно из решений - снова добавить стратегии исключения к объекту 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, и они решат ее в следующем выпуске.