簡體   English   中英

Gson:序列化期間出現 StackOverflowError

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM