java - 如何用 Jackson 序列化/反序列化 DefaultMutableTreeNode?
问题描述
我们如何DefaultMutableTreeNode
使用 Jackson 将 Swing 序列化/反序列化到 JSON 或从 JSON 序列化/反序列化?
有一个相关的问题 How to serialize DefaultMutableTreeNode (Java) to JSON? . 但它要求 Gson,而不是 Jackson(仅用于序列化,而不用于反序列化)。
对于DefaultMutableTreeNode
Jackson 的默认序列化/序列化不起作用,原因有很多:
- 它包含再次是
DefaultMutableTreeNode
对象的子项。但它没有规范的 getter 和 setter 方法(如getChildren()
andsetChildren(...)
)。 - 它包含反向引用(通过方法
getParent()
,getRoot()
,getPath()
),这将导致序列化期间的无限递归和 StackOverflow。 - 它有许多不需要序列化的冗余 getter 方法(如
isLeaf()
,getNextSibling()
, , ...),因为它们是从其他属性派生的。getLastChild()
解决方案
您可以ObjectMapper
使用 a
自定义 Jackson'sJsonSerializer
并JsonDeserializer
专门用于将 a 转换DefaultMutableTreeNode
为 JSON,反之亦然。
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new SimpleModule()
.addSerializer(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeSerializer())
.addDeserializer(DefaultMutableTreeNode.class, new DefaultMutableTreeNodeDeserializer()))
.enable(SerializationFeature.INDENT_OUTPUT);
下面DefaultMutableTreeNodeSerializer
负责将 a 转换DefaultMutableTreeNode
为 JSON。它将allowsChildren
,userObject
和children
of写入DefaultMutableTreeNode
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();
}
}
为了测试,您可以序列化 sample 的根节点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,因此不能与杰克逊一起很好地工作。因此,我创建了一个表现良好的POJO
帮助器类(具有属性
和) allowsChildren
,并让 Jackson 将 JSON 内容反序列化到该类中。然后我将对象(及其
子对象)转换为对象(带有子对象)。userObject
children
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;
}
}
}
推荐阅读
- reactjs - 上传的 React Quill 图像是像素化的
- python - 将 ndarray 写入二进制并以正确的形状读取
- c++ - QT Creator 中的 OpenSSL 不起作用——如何正确设置?
- dart - 如何在built_value EnumClass 中定义字段?
- python - 遍历一系列 GenBank 基因并将每个基因的特征附加到列表中仅返回最后一个基因
- django - 角度重定向到同一主机上的后端应用程序
- sql-server - 修改现有小数位信息
- python - 使用 numpy loadtxt 将 CSV 文件导入 Google Colab
- laravel - 如何获取父母孩子的孩子的数据?Laravel 雄辩
- windows - 在 Windows 中使用 ZeroMQ 的 Erlang