簡體   English   中英

如何使用Jackson序列化/反序列化DefaultMutableTreeNode?

[英]How to serialize/deserialize a DefaultMutableTreeNode with Jackson?

我們如何使用Jackson將Swing的DefaultMutableTreeNode序列化到JSON或從JSON反序列化?

有一個相關的問題, 如何將DefaultMutableTreeNode(Java)序列化為JSON? 但是它要求使用Gson,而不是Jackson(並且僅要求序列化,而不要求反序列化)。

對於DefaultMutableTreeNode ,由於多種原因,傑克遜的默認序列化/序列化不起作用:

  • 它包含再次是DefaultMutableTreeNode對象的子級。 但是它沒有規范的getter和setter方法(例如getChildren()setChildren(...) )。
  • 它包含反向引用(通過方法getParent()getRoot()getPath() ),這將導致序列化期間的無限遞歸和StackOverflow。
  • 它具有許多冗余的getter方法(例如isLeaf()getNextSibling()getLastChild() ,...),這些方法不需要序列化,因為它們是從其他屬性派生的。

您可以使用JsonSerializerJsonDeserializer自定義Jackson的ObjectMapperJsonSerializerJsonDeserializer專為將DefaultMutableTreeNode轉換為JSON(反之亦然)而設計。

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

下面的DefaultMutableTreeNodeSerializer負責將DefaultMutableTreeNode轉換為JSON。 它將DefaultMutableTreeNodeallowsChildrenuserObjectchildren寫入JSON。 它不會寫入parent ,因為這將導致無限遞歸和StackOverflowError。 而是將父子關系編碼為JSON輸出的嵌套結構。

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的根節點,然后再次對其進行反序列化。

樹

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輸出:

{
  "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

DefaultMutableTreeNode非常不像POJO,因此不能與Jackson一起很好地工作。 因此,我創建了一個行為良好的POJO幫助器類(具有屬性allowsChildrenuserObjectchildren ),並讓Jackson將JSON內容反序列化到該類中。 然后,我將POJO對象(及其POJO子對象)轉換為DefaultMutableTreeNode對象(具有DefaultMutableTreeNode子對象)。

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;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM