如何使用Jackson序列化/反序列化DefaultMutableTreeNode? [英] How to serialize/deserialize a DefaultMutableTreeNode with Jackson?

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

问题描述

我们如何序列化/反序列化Swing的 DefaultMutableTreeNode 与杰克逊(Jackson)之间的JSON互斥?

How can we serialize/deserialize Swing's DefaultMutableTreeNode to/from JSON with Jackson?

有一个相关的问题 如何将DefaultMutableTreeNode(Java)序列化为JSON?. 但它要求的是Gson,而不是Jackson(仅 用于序列化,而不用于反序列化.

There is a related question How to serialize DefaultMutableTreeNode (Java) to JSON?. But it asked for Gson, not Jackson (and only for serialization, not for deserialization).

对于DefaultMutableTreeNode Jackson的默认设置 出于多种原因,序列化/序列化无法正常工作

For DefaultMutableTreeNode Jackson's default serialization/serialization doesn't work, for various reasons:

  • 它包含又是DefaultMutableTreeNode对象的子级. 但是它没有规范的getter和setter方法 (如getChildren()setChildren(...)).
  • 它包含反向引用(通过方法getParent()getRoot()getPath()),这将导致无限递归和StackOverflow 在序列化期间.
  • 它具有许多冗余的吸气剂方法(例如isLeaf()getNextSibling()getLastChild(),...) 要序列化,因为它们是从其他属性派生的.
  • It contains children which again are DefaultMutableTreeNode objects. But it doesn't have the canonical getter and setter methods for that (like getChildren() and setChildren(...)).
  • It contains back-references (via methods getParent(), getRoot(), getPath()) which would lead to infinite recursion and StackOverflow during serialization.
  • It has many redundant getter methods (like isLeaf(), getNextSibling(), getLastChild(), ...) which don't need to be serialized, because they are derived from other properties.

推荐答案

您可以使用 JsonSerializer

You can to customize Jackson's ObjectMapper with a JsonSerializer and JsonDeserializer specially crafted for converting a DefaultMutableTreeNode to JSON and vice versa.

ObjectMapper objectMapper = new ObjectMapper()
    .registerModule(new SimpleModule()
        .addSerializer(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeSerializer())
        .addDeserializer(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeDeserializer()))
    .enable(SerializationFeature.INDENT_OUTPUT);

下面的DefaultMutableTreeNodeSerializer是负责任的 用于将DefaultMutableTreeNode转换为JSON. 它写入allowsChildrenuserObjectchildren DefaultMutableTreeNode转换为JSON. 它不会写parent,因为那样会 导致无限递归和StackOverflowError. 而是将父子关系编码为嵌套 JSON输出的结构.

The DefaultMutableTreeNodeSerializer below is responsible for converting a DefaultMutableTreeNode to JSON. It writes the allowsChildren, userObject and children of DefaultMutableTreeNode to JSON. It does not write its parent, because that would lead to infinite recursion and StackOverflowError. Instead, the parent-child relations are encoded in the nested structure of the JSON-output.

public class DefaultMutableTreeNodeSerializer extends JsonSerializer<DefaultMutableTreeNode> {

    @Override
    public void serialize(DefaultMutableTreeNode node, JsonGenerator gen, SerializerProvider serializers)
            throws IOException {
        gen.writeStartObject();
        gen.writeBooleanField("allowsChildren", node.getAllowsChildren());
        gen.writeObjectField("userObject", node.getUserObject());
        if (node.getChildCount() > 0)
            gen.writeObjectField("children", Collections.list(node.children()));
        // Don't write node.getParent(), it would lead to infinite recursion.
        gen.writeEndObject();
    }
}

对于测试,您可以序列化示例JTree的根节点, 然后再次反序列化.

For testing you can serialize the root node of a sample JTree, and then deserialize it again.

JTree tree = new JTree(); // a sample tree
Object root = tree.getModel().getRoot(); // a DefaultMutableTreeNode
String json = objectMapper.writeValueAsString(root);
System.out.println(json);
DefaultMutableTreeNode root2 = objectMapper.readValue(json, 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.

DefaultMutableTreeNode非常类似于POJO 因此无法与Jackson一起使用. 因此,我创建了行为良好的POJO助手类 (具有属性allowsChildrenuserObjectchildren) 然后让Jackson将JSON内容反序列化到此类中. 然后,我转换POJO对象(及其POJO 子级)到DefaultMutableTreeNode对象 (有DefaultMutableTreeNode个孩子).

The DefaultMutableTreeNode is very not POJO-like and thus doesn't work well together with Jackson. Therefore I created a well-behaving POJO helper class (with properties allowsChildren, userObject and children) and let Jackson deserialize the JSON content into this class. Then I convert the POJO object (and its POJO children) to a DefaultMutableTreeNode object (with DefaultMutableTreeNode children).

public class DefaultMutableTreeNodeDeserializer extends JsonDeserializer<DefaultMutableTreeNode> {

    @Override
    public DefaultMutableTreeNode deserialize(JsonParser parser, DeserializationContext context)
            throws IOException {
        return parser.readValueAs(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 Jackson'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;
        }
    }
}

这篇关于如何使用Jackson序列化/反序列化DefaultMutableTreeNode?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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