Jackson deserializing recursive object

deserialization, jackson, json, recursion, serialization

Solution

@vinodv26 In NodeDeserializer it's not the most efficient way to use the `ObjectMapper` class to parse (again) the JSON of the embedded `Node`. Instead of:

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

It's better to use:

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

Or, if what you were looking for is to simply ignore the `embeddedNodes` attribute when it's empty, you can use `mapper.setSerializationInclusion(Include.NON_EMPTY)` or annotate the `Node` class with `@JsonInclude(Include.NON_EMPTY)`. This way you don't need custom serialization or deserialization classes, but you need to remove the `final` modifier in the `Node` attributes and add an empty constructor and setters.

Problem

I have a recursive object Node.java which I am able to serialize using Jackson but unable to deserialize it back. 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; } } ``` Jackson serializer ``` 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(); } } ``` Sample Node instance ``` 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 generated: ``` { "id": "3", "embeddedNodes": { "second": { "id": "2" }, "first": { "id": "1", "embeddedNodes": { "zero": { "id": "0" } } } } } ``` But I am unable to write corresponding deserializer for this, any help is appreciated. ``` class NodeDeserializer extends JsonDeserializer<Node> { @Override public Node deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { //how do we write this?? return null; } } ```

Original source