Gson,序列化一个树形结构

zbwhf8kr  于 2022-11-23  发布在  其他
关注(0)|答案(3)|浏览(248)

下面是一个例子,我想用这个例子来说明我的代码。

public class TreeNode {
private TreeNode parent;
private ArrayList<TreeNode> children;
private Object value;
    //methods
}

我的GSon调用如下所示:

TreeNode headNode = getHeadNode();
    Gson gson = new Gson();
    Type typeOfSrc = new TypeToken<TreeNode>(){}.getType();
    String gsonTreeString = gson.toJson(headNode,typeOfSrc);

headNode至少有一个子对象时,堆栈溢出发生了,我不明白为什么。有人能告诉我我做错了什么吗?

tquggr8v

tquggr8v1#

在Gson中,您可以创建一个自定义适配器来序列化表示树的数据结构。您需要的是序列化节点及其所有子节点。实现此目的的技巧是递归调用write方法来填充JsonWriter。以下代码应该适用于您的示例:

public class TreeNodeAdapter extends TypeAdapter<TreeNode> {

    @Override
    public void write(JsonWriter jsonWriter, TreeNode node) throws IOException {
        jsonWriter.beginObject()
                .name("coordinates")
                .jsonValue("\"" + node.getValue + "\"")
                .name("children")
                .beginArray();
        // Recursive call to the children nodes
        for (Node c : node.getChildren()) {
            this.write(jsonWriter, c);
        }
        jsonWriter.endArray()
                .endObject();
    }

    @Override
    public Node read(JsonReader jsonReader) throws IOException {
        return null;
    }
}

然后,要使用TreeNodeAdapter,只需示例化NodeTree并使用GsonBuilder和自定义适配器来序列化对象。

NodeTree tree = new NodeTree(...);
        NodeAdapter nodeAdapter = new NodeAdapter();
        GsonBuilder gsonBuilder = new GsonBuilder().registerTypeAdapter(NodeTree.class, nodeAdapter);
        Gson gson = gsonBuilder.create();
        gson.toJson(tree); // JSON string
pjngdqdw

pjngdqdw2#

成员父代指向其父代,而其父代又有一个子代指向子代,而子代又有一个父代指向父代...

dz6r00yl

dz6r00yl3#

Will是对的,问题是,有一个无限的路径要保存。你可以通过不保存父对象来解决这个问题。你可以在从JSON对象读取时设置父对象。为了避免保存父对象,只需将其设置为transient。

public class TreeNode {
private transient TreeNode parent;
private ArrayList<TreeNode> children;
private Object value;
    //methods
}

当转换回POJO时,您将调用下面的setParent-method。

TreeNode newRoot = gson.fromJson(treeJson, TreeNode.class);
setParents(newRoot);

setParents-method只遍历节点的所有子节点,并将它们的父节点设置为将该节点作为子节点的节点。

private void setParents(TreeNode root) {
        for (TreeNode  node : root.getChildren()) {
            node.setParent(root);
            setParents(node);
        }
    }

相关问题