Вы можете настроить Джексона 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.
Это пишет allowsChildren
, userObject
и children
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();
}
}
Для тестирования вы можете сериализовать корневой узел образца 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
, userObject
и children
)
и пусть Джексон десериализует контент 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;
}
}
}