【问题标题】:Getting stackoverflowerror from Gson while converting hashmap to JSON object在将 hashmap 转换为 JSON 对象时从 Gson 获取 stackoverflowerror
【发布时间】:2017-02-26 00:46:51
【问题描述】:

我想将树结构中的数据表示为 java 对象,然后我想将其转换为 JSON 对象。

借助stackoverflow条目:

Convert java arrayList of Parent/child relation into tree?

hashmap to JSON using GSON

我有下面的主要功能和“对”列表包含一对:孩子和父母

ArrayList<Pair> list= new ArrayList<>();
list.add(new Pair("6", "4"));
list.add(new Pair("5", "4"));
list.add(new Pair("4", "3"));
list.add(new Pair("2", "3"));
list.add(new Pair("3", "null"));

Map<String, Node> o_map= new HashMap<>();
for (Pair l: list) {
Node parent = o_map.getOrDefault(l.getParentId(), new Node(l.getParentId()));
Node child = o_map.getOrDefault(l.getChildId(), new Node(l.getChildId()));
parent.children.add(child);
child.parent = parent;
o_map.put(parent.id, parent);
o_map.put(child.id, child);
}
Gson gs = new Gson();
System.out.println(gs.toJson(o_map));
}

但是此代码返回:

Exception in thread "main" java.lang.StackOverflowError
    at java.io.StringWriter.write(StringWriter.java:112)
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:576)
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402)
    at com.google.gson.stream.JsonWriter.beginArray(JsonWriter.java:287)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:95)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:968)

错误。

我不明白为什么它会返回这样的错误。 可能是什么原因? 非常感谢您。

【问题讨论】:

  • 我需要做的是将 hashmap> 转换为 json 对象。
  • 你应该这样写吗ArrayList&lt;Pair&gt; list= new ArrayList&lt;Pair&gt;();
  • 我需要在 json 中有树形结构。为此,我需要将 hashmap 转换为 json。我尝试了另一种选择,将一对列表写入 json,但结果不是我想要的。
  • 结果不是我想要的” - 分享您正在寻找的结果会很有帮助。包括 Node 的定义也会有所帮助,因为这就是您要序列化的内容。

标签: json hashmap gson


【解决方案1】:

您没有包含您的 Node 类定义,但我猜它看起来像这样:

public class Node {
  public final String id;
  public Node parent;
  public final ArrayList<Node> children = new ArrayList<>();

  public Node(String id) {
    this.id = id;
  }
}

这是在内存中表示树形数据结构的好方法(忽略一些不相关的样式问题,例如使用公共字段),但无法序列化。为什么?因为任何带有非空parentNode 都具有循环关系——子代包含对其父代的引用,而父代又包含对子代的引用,子代又包含对父代的引用,而父代又包含对父代的引用包含.....

来自user guide

请注意,您不能使用循环引用序列化对象,因为这将导致无限递归。

我们可以用这个更简单的例子触发同样的错误:

Node root = new Node("A");
Node child = new Node("B");
root.children.add(child);
child.parent = root;
System.out.println(new Gson().toJson(root)); // passing in child would similarly fail

那么我们该如何解决这个问题呢?这取决于你想要什么行为。一个简单的选择是阻止 Gson 尝试序列化 parent 字段(我们不需要它,因为我们可以从 children 列表中重建它)。要做到这一点只需mark parent as transient,Gson 不会将其包含在结果中。如果明确记录父关系更有帮助,您可以类似地将children 设置为transient 字段。然而,序列化children 字段的一个好处是您可以只传入根节点,然后将遍历整个树。

另一种选择是序列化与Map&lt;String, Node&gt; 不同的数据结构 - 您当前正在将每个节点 ID 映射到其 Node 对象(传递地,它包含对所有其他节点的引用),这意味着即使您修复循环关系,结果你仍然会得到一些奇怪的 JSON。 似乎您真正想要的只是序列化 ID -> 父级或 ID -> 子级关系,这将是 Gson 没有的 Map&lt;String, String&gt;Map&lt;String, List&lt;String&gt;&gt; 数据结构序列化麻烦。如果这是您想要的结构,您可以简单地遍历您的树并首先构建这样的数据结构,或者定义一个 custom deserializerNode 转换为您想要的确切 JSON 结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 2020-07-15
    • 2011-02-16
    • 1970-01-01
    相关资源
    最近更新 更多