[英]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。 isLeaf()
, getNextSibling()
, getLastChild()
,...),這些方法不需要序列化,因為它們是從其他屬性派生的。 您可以使用JsonSerializer
和JsonDeserializer
自定義Jackson的ObjectMapper
, JsonSerializer
和JsonDeserializer
專為將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。 它將DefaultMutableTreeNode
的allowsChildren
, userObject
和children
寫入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
幫助器類(具有屬性allowsChildren
, userObject
和children
),並讓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.