杰克逊反序列化递归对象

时间:2014-04-24 22:10:15

标签: json serialization recursion jackson deserialization

我有一个递归对象Node.java,我可以使用Jackson序列化,但无法将其反序列化。

Node.java

    public class Node {
        private final String id;
        private final Map<String, Node> embeddedNodes;

        public Node(String id, Map<String, Node> embeddedNodes) {
            this.id = id;
            this.embeddedNodes = embeddedNodes;
        }

        public String getId() {
            return id;
        }

        public Map<String, Node> getEmbeddedNodes() {
            return embeddedNodes;
        }
}

杰克逊序列化

public static class NodeSerializer extends JsonSerializer<Node> {
        @Override
        public void serialize(Node node, JsonGenerator jgen, SerializerProvider provider) throws IOException{
            jgen.writeStartObject();
            jgen.writeStringField("id", node.getId());

            Map<String, Node> embeddedNodesMap = node.getEmbeddedNodes();
            if (!embeddedNodesMap.isEmpty()) {
                jgen.writeObjectFieldStart("embeddedNodes");
                for (Map.Entry<String, Node> entry : embeddedNodesMap.entrySet()) {
                    jgen.writeObjectField(entry.getKey(), entry.getValue());
                }
                jgen.writeEndObject();
            }

            jgen.writeEndObject();

        }
    }

示例节点实例

Node node0 = new Node("0", Maps.<String, Node>newHashMap());
Map<String, Node> embeddedNodes1 = Maps.newHashMap();
embeddedNodes1.put("zero", node0);
Node node1 = new Node("1", embeddedNodes1);
Node node2 = new Node("2", Maps.<String, Node>newHashMap());
Map<String, Node> embeddedNodes = Maps.newHashMap();
embeddedNodes.put("first", node1);
embeddedNodes.put("second", node2);
Node node3 = new Node("3", embeddedNodes);

String jsonStr = mapper.writeValueAsString(node3);

生成JSON:

{
    "id": "3",
    "embeddedNodes": {
        "second": {
            "id": "2"
        },
        "first": {
            "id": "1",
            "embeddedNodes": {
                "zero": {
                    "id": "0"
                }
            }
        }
    }
}

但是我无法为此编写相应的反序列化器,任何帮助都表示赞赏。

class NodeDeserializer extends JsonDeserializer<Node> {
        @Override
        public Node deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            //how do we write this??
            return null;
        }
    }

2 个答案:

答案 0 :(得分:1)

@ vinodv26在 NodeDeserializer 中,它不是使用ObjectMapper类来解析(再次)嵌入式Node的JSON的最有效方法。而不是:

Node embedNode = mapper.readValue(jsonNode.toString(), Node.class);

最好使用:

Node embedNode = jp.getCodec().treeToValue(jsonNode, Node.class);

或者,如果您要查找的内容是在embeddedNodes属性为空时忽略它,则可以使用mapper.setSerializationInclusion(Include.NON_EMPTY)或使用{{Node类注释1}}。这样您就不需要自定义序列化或反序列化类,但您需要删除@JsonInclude(Include.NON_EMPTY)属性中的final修饰符并添加空构造函数和setter。

答案 1 :(得分:0)

经过几次尝试后,我想出了以下解串器,但不确定这是否是正确的方法:

private static class NodeDeserializer extends JsonDeserializer<Node> {
        @Override
        public Node deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            JsonNode node = jp.getCodec().readTree(jp);
            String id = node.get("id").asText();
            Map<String, Node> embeddedNodes = Maps.newHashMap();
            JsonNode embeddedNodesJsonNode = node.get("embeddedNodes");
            if (embeddedNodesJsonNode != null) {
                Iterator<String> embeddedElementNames = embeddedNodesJsonNode.fieldNames();
                while (embeddedElementNames.hasNext()) {
                    String embedName = embeddedElementNames.next();
                    JsonNode jsonNode = embeddedNodesJsonNode.get(embedName);
                    Node embedNode = mapper.readValue(jsonNode.toString(), Node.class);
                    embeddedNodes.put(embedName, embedNode);
                }
            }

            return new Node(id, embeddedNodes);
        }
    }