繁体   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