[英]Gson: StackOverflowError during serialization
我寫了這個class,我需要序列化字段gameTimer,它的類型是接口TimerP。
public class PlayerImpl implements Player {
@Expose
private final String nickname;
@Expose
private final TimerP gameTimer;
@Expose
private final int finalScore;
為了解決這個問題,我寫了一個 interfaceAdapter:
public class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {
private static final String CLASSNAME = "CLASSNAME";
private static final String DATA = "DATA";
@Override
public T deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
String className = prim.getAsString();
Class<?> c = this.getObjectClass(className);
return context.deserialize(jsonObject.get(DATA), c);
}
@Override
public JsonElement serialize(final T src, final Type typeOfSrc, final JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(CLASSNAME, src.getClass().getName());
jsonObject.add(DATA, context.serialize(src));
return jsonObject;
}
/****** Helper method to get the className of the object to be deserialized. *****/
private Class<?> getObjectClass(final String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
//e.printStackTrace();
throw new JsonParseException(e.getMessage());
}
}
但在嘗試序列化 object 時會出現此異常:
Caused by: java.lang.StackOverflowError
at com.google.gson.internal.$Gson$Types.canonicalize($Gson$Types.java:104)
at com.google.gson.reflect.TypeToken.<init>(TypeToken.java:72)
at com.google.gson.reflect.TypeToken.get(TypeToken.java:296)
at com.google.gson.Gson.toJson(Gson.java:696)
at com.google.gson.Gson.toJsonTree(Gson.java:597)
at com.google.gson.Gson.toJsonTree(Gson.java:576)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
at common.InterfaceAdapter.serialize(InterfaceAdapter.java:33)
at common.InterfaceAdapter.serialize(InterfaceAdapter.java:15)
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
at com.google.gson.Gson.toJson(Gson.java:704)
at com.google.gson.Gson.toJsonTree(Gson.java:597)
at com.google.gson.Gson.toJsonTree(Gson.java:576)
at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
這是我在文件上讀寫的 class:
public class LeaderboardImpl implements Leaderboard {
private final File directory = new File(System.getProperty("user.home"), ".unitype");
private final File file = new File(directory, FILE_NAME);
private static final String FILE_NAME = "unitype.json";
/**
* Returns the instance of this class.
*
* @return the instance of this class
*/
public static LeaderboardImpl getLeaderboard() {
return LazyHolderLeaderboard.SINGLETON;
}
/**
* {@inheritDoc}
*/
@Override
public void addPlayer(final Player p) {
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.registerTypeHierarchyAdapter(TimerP.class, new InterfaceAdapter<TimerP>())
.create();
final List<Player> playersList = this.getPlayersList();
playersList.add(p);
final String json = gson.toJson(playersList);
this.checkFile();
try (FileWriter writer = new FileWriter(file)) {
writer.write(json);
writer.flush();
} catch (JsonIOException | IOException e) {
e.printStackTrace();
}
}
/**
* {@inheritDoc}
*/
@Override
public List<Player> getPlayersList() {
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.registerTypeHierarchyAdapter(TimerP.class, new InterfaceAdapter<TimerP>())
.create();
List<Player> playersList = new ArrayList<>();
this.checkFile();
try (JsonReader jsonReader = new JsonReader(new FileReader(file))) {
final JsonElement js = JsonParser.parseReader(jsonReader);
if (js.isJsonObject()) {
final JsonObject jsonObject = js.getAsJsonObject();
playersList.add(gson.fromJson(jsonObject, PlayerImpl.class));
} else if (js.isJsonArray()) {
playersList = gson.fromJson(js,
new TypeToken<List<PlayerImpl>>() { }.getType());
}
} catch (JsonSyntaxException | JsonIOException | IOException e) {
e.printStackTrace();
}
return playersList;
}
我嘗試了所有方法,但找不到任何解決方案,我不明白為什么它不起作用
對於海報來說已經太晚了,但也許對於任何也陷入這個陷阱的人(比如我)來說。 互聯網上的一些博客也提出了這個解決方案。 但是,他們使用registerTypeAdapter而不是registerTypeHierarchyAdapter 。
有趣的說明:反之亦然, registerTypeAdapter導致堆棧溢出並且registerTypeHierarchyAdapter起作用,請參見此處。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.