How To Use Jackson's @JsonIdentityInfo for Deserialization of directed Graphs?
Asked Answered
E

1

8

I want to use Jackson 2.3.3 for Deserialization/Serialization of directed graphs. The structure I came up with is roughly the following:

public Class Graph {
    private final Set<Node> nodes;
    public Graph(Set<Node> nodes) { ... }
    public Set<Node> getNodes() { ... }
}

@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "name")
public Class Node {
    private final String name;
    private final Set<Edge> edges;
    public Node(String name, Set<Edge> edges) { ... }
    public String getName() { ... }
    public Set<Edge> getEdges() { ... }
}

@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "name")
public Class Edge {
    private final String name;
    private final Node successor;
    public Edge(String name, Node successor) { ... }
    public String getName() { ... }
    public Node getSuccessor() { ... }
}

And I expect to have this JSON-Structure:

{
  "graph": [{
    "name": "A",
    "edges": [{
      "name": "0",
      "successor": "B"
    }, {
      "name": "1",
      "successor": "A"
    }]
  }, {
    "name": "B",
    "edges": [{
      "name": "0",
      "successor": "A"
    }, {
      "name": "1",
      "successor": "B"
    }]
  }]
}

But I get the following error while deserialization (even with annotation @JsonProperty("name") at the Getters):

com.fasterxml.jackson.databind.JsonMappingException: Invalid Object Id definition for some.package.graph.Node: can not find property with name 'name'

I have found some solutions for Jackson 1.6 with Back-Reference Annotations, but I'd like to use the new Jackson 2.x Annotation, as it was advertised so much in the API Update from 1.9 to 2.0 of Jackson.

What point am I missing here? Thanks for constructive answers in advance.

EDIT

(Removed my answer from here to the Answer section)

Epigraphic answered 22/7, 2014 at 14:42 Comment(0)
E
3

I got kind of blind of staring too long at it. Here's what's gone wrong:

The Serialization actually worked as intended. What didn't work was the Deserialization, because Jackson wasn't able to instantiate my Node-Object. I simply forgot to annotate the parameters of the constructor methods correctly.

I was now facing another problem. The generated JSON now looked like this:

"graph": {
  "nodes": [{
    "name": "B",
    "edges": [{
      "label": "1",
      "successor": "B"
    }, {
      "label": "0",
      "successor": {
        "name": "A",
        "edges": [{
          "label": "1",
          "successor": "A"
        }, {
          "label": "0",
          "successor": "B"
        }]
      }
    }]
  }, "A"]
}

So far so good. But during mapping, Jackson confronts me with this Error:

java.lang.IllegalStateException: Could not resolve Object Id [B] (for [simple
type, class some.package.graph.Node]) -- unresolved forward-reference?

I even changed the Label of the edges because I thought the same property name might confuse Jackson here, but that didn't help either...

My guess here is that Jackson can't reference the Node B, because it is still being constructed (you could say it is actually some kind of root in this example). The only way to fix this seems to construct all the Nodes without the edges and inject them in a second step.

Epigraphic answered 23/7, 2014 at 5:27 Comment(4)
Jackson version 2.4 added support for forward references, meaning that regardless of ordering of JSON input, all object id references can be succesfully resolved. So solution may be as simple as upgrade.Biaxial
Thanks for the update! Unfortunately, the university project, that this feature was intended for, is already over with this feature being scrapped. I'll keep it in mind for the next time using the Jackson-Library.Epigraphic
If I take your example, what if I want the whole object for node name A as well instead of just "A" as second element in graph JSON array?Shrunk
Could you please write out what you did to solve "forgot to annotate the parameters of the constructor methods correctly" so that we can see the actual solution? thx in advance!Clothier

© 2022 - 2024 — McMap. All rights reserved.