如何使用Jackson序列化/反序列化DefaultMutableTreeNode? [英] How to serialize/deserialize a DefaultMutableTreeNode with Jackson?
问题描述
我们如何序列化/反序列化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 (likegetChildren()
andsetChildren(...)
). - 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.
它写入allowsChildren
,userObject
和children
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
助手类
(具有属性allowsChildren
,userObject
和children
)
然后让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屋!