如何将DefaultMutableTreeNode(Java)序列化为JSON? [英] How to serialize DefaultMutableTreeNode (Java) to JSON?

查看:182
本文介绍了如何将DefaultMutableTreeNode(Java)序列化为JSON?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将树(使用DefaultMutableTreeNode类在Java中实现)序列化为JSON(用于通过RESTful方法传输到iOS客户端)?

How can I serialize a tree (implemented in Java using the DefaultMutableTreeNode class) to JSON (for transferring via RESTful method to an iOS client)?

我尝试过:

String jsonString = (new Gson()).toJson(topNode);
// topNode is DefaultMutableTreeNode at the root

它与StackOverflowError一起崩溃了.

推荐答案

Swing的

Swing's DefaultMutableTreeNode class is a tree-like data structure which contains instances of this same type both as children and as parent. That's why Gson's default serializer ran into infinite recursion and hence threw a StackOverflowError.

要解决此问题,您需要使用更聪明的 JsonDeserializer 将此类JSON转换回DefaultMutableTreeNode.

To solve this problem you need to customize your Gson with a smarter JsonSerializer specially crafted for converting a DefaultMutableTreeNode to JSON. As a bonus you might also want to provide a JsonDeserializer for converting such JSON back to a DefaultMutableTreeNode.

为此,不仅可以通过new Gson(),还可以通过

For that create your Gson instance not just by new Gson(), but by

Gson gson = new GsonBuilder()
        .registerTypeAdapter(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeSerializer())
        .registerTypeAdapter(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeDeserializer())
        .setPrettyPrinting()
        .create();

下面的DefaultMutableTreeNodeSerializer是负责任的 用于将DefaultMutableTreeNode转换为JSON. 它将其属性allowsChildrenuserObjectchildren转换为JSON. 请注意,它不会将parent属性转换为JSON, 因为这样做会再次产生无限递归.

The DefaultMutableTreeNodeSerializer below is responsible for converting a DefaultMutableTreeNode to JSON. It converts its properties allowsChildren, userObject and children to JSON. Note that it does not convert the parent property to JSON, because doing that would produce an inifinite recursion again.

public class DefaultMutableTreeNodeSerializer implements JsonSerializer<DefaultMutableTreeNode> {

    @Override
    public JsonElement serialize(DefaultMutableTreeNode src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("allowsChildren", src.getAllowsChildren());
        jsonObject.add("userObject", context.serialize(src.getUserObject()));
        if (src.getChildCount() > 0) {
            jsonObject.add("children", context.serialize(Collections.list(src.children())));
        }
        return jsonObject;
    }
}

为了进行测试,让我们将示例JTree的根节点序列化为JSON, 然后再次反序列化.

For testing let us serialize the root node of a sample JTree to JSON, and then deserialize it again.

JTree tree = new JTree();  // create a sample tree
Object topNode = tree.getModel().getRoot();  // a DefaultMutableTreeNode
String jsonString = gson.toJson(topNode);
System.out.println(jsonString);
DefaultMutableTreeNode topNode2 = gson.fromJson(jsonString, DefaultMutableTreeNode.class);

它将生成以下JSON输出:

It generates the following JSON output:

{
  "allowsChildren": true,
  "userObject": "JTree",
  "children": [
    {
      "allowsChildren": true,
      "userObject": "colors",
      "children": [
        {
          "allowsChildren": true,
          "userObject": "blue"
        },
        {
          "allowsChildren": true,
          "userObject": "violet"
        },
        {
          "allowsChildren": true,
          "userObject": "red"
        },
        {
          "allowsChildren": true,
          "userObject": "yellow"
        }
      ]
    },
    {
      "allowsChildren": true,
      "userObject": "sports",
      "children": [
        {
          "allowsChildren": true,
          "userObject": "basketball"
        },
        {
          "allowsChildren": true,
          "userObject": "soccer"
        },
        {
          "allowsChildren": true,
          "userObject": "football"
        },
        {
          "allowsChildren": true,
          "userObject": "hockey"
        }
      ]
    },
    {
      "allowsChildren": true,
      "userObject": "food",
      "children": [
        {
          "allowsChildren": true,
          "userObject": "hot dogs"
        },
        {
          "allowsChildren": true,
          "userObject": "pizza"
        },
        {
          "allowsChildren": true,
          "userObject": "ravioli"
        },
        {
          "allowsChildren": true,
          "userObject": "bananas"
        }
      ]
    }
  ]
}

下面的DefaultMutableTreeNodeDeserializer是负责任的 用于将JSON转换回DefaultMutableTreeNode.

The DefaultMutableTreeNodeDeserializer below is responsible for converting JSON back to a DefaultMutableTreeNode.

它使用与解串器相同的想法 如何与Jackson一起对DefaultMutableTreeNode进行序列化/反序列化?一个>. DefaultMutableTreeNode不是很像POJO,因此不是 与Gson一起工作得很好. 因此,它使用行为良好的POJO助手类(带有属性 allowsChildrenuserObjectchildren),然后让Gson 将JSON内容反序列化到此类中. 然后,POJO对象(及其POJO子对象)将转换为 DefaultMutableTreeNode对象(具有DefaultMutableTreeNode个子对象).

It uses the same idea as the deserializer from How to serialize/deserialize a DefaultMutableTreeNode with Jackson?. The DefaultMutableTreeNode is not very POJO-like and thus doesn't work well together with Gson. Therefore it uses a well-behaving POJO helper class (with properties allowsChildren, userObject and children) and lets Gson deserialize the JSON content into this class. Then the POJO object (and its POJO children) is converted to a DefaultMutableTreeNode object (with DefaultMutableTreeNode children).

public class DefaultMutableTreeNodeDeserializer implements JsonDeserializer<DefaultMutableTreeNode> {

    @Override
    public DefaultMutableTreeNode deserialize(JsonElement json, Type type, JsonDeserializationContext context) {
        return context.<POJO>deserialize(json, POJO.class).toDefaultMutableTreeNode();
    }

    private static class POJO {

        private boolean allowsChildren;
        private Object userObject;
        private List<POJO> children;
        // no need for: POJO parent

        public DefaultMutableTreeNode toDefaultMutableTreeNode() {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode();
            node.setAllowsChildren(allowsChildren);
            node.setUserObject(userObject);
            if (children != null) {
                for (POJO child : children) {
                    node.add(child.toDefaultMutableTreeNode()); // recursion!
                    // this did also set the parent of the child-node
                }
            }
            return node;
        }

        // Following setters needed by Gson's deserialization:

        public void setAllowsChildren(boolean allowsChildren) {
            this.allowsChildren = allowsChildren;
        }

        public void setUserObject(Object userObject) {
            this.userObject = userObject;
        }

        public void setChildren(List<POJO> children) {
            this.children = children;
        }
    }
}

这篇关于如何将DefaultMutableTreeNode(Java)序列化为JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆