Feature: Handle bi-directional references using declarative method(s)

(see Jira entry JACKSON-235 for more details)

Before Jackson 1.5, back references such as "parent" links from child objects, previous sibling for doubly-linked lists, and general bi-directional references for ORM-managed beans (iBatis, Hibernate) would cause serialization to failure since they are cyclic dependencies.

In Jackson 1.6 there are 2 new annotations that allow specifying relationship between 2 properties that form such bi-directional dependency so that Jackson can properly omit cycle during serialization, and re-construct during serialization.

New annotations

Annotations are:

These annotations can be used for:

* Methods (getters and setters) * Fields

but not for types (classes) or constructor arguments.

Annotations take optional "name" parameter; if omitted default name is used. Name is needed to allow multiple reference pairs for one bean type.

Example

Here is a simple example of a double-linked linked list, where references are both in same class

public class Node
{
    public String name; // simple property

    // reference with default name        
    @JsonManagedReference public SimpleTreeNode child; // forward reference, serialized
    @JsonBackReference public Node parent; // backward reference, not serialized

    public SimpleTreeNode() { this(null); }
    public SimpleTreeNode(String n) { name = n; }

Linkage also works for structured types (arrays, Collections, Maps), as long as only forward reference is of such type. For example:

public class NodeList
{
    @JsonManagedReference
    public List<NodeForList> nodes;
}

public class NodeForList
{
    public String name;
      
    @JsonBackReference public NodeList parent;

    public NodeForList() { this(null); }
    public NodeForList(String n) { name = n; }
}

and it is possible to use multiple references, by specifying distinct names:

public class FullTreeNode
{
    public String name;

    // parent-child links
    @JsonBackReference("parent")
    public FullTreeNode parent;
    @JsonManagedReference("parent")
    public FullTreeNode firstChild;

    // sibling-links
    @JsonManagedReference("sibling")
    public FullTreeNode next;
    @JsonBackReference("sibling")
    protected FullTreeNode prev;
        
    public FullTreeNode() { this(null); }
    public FullTreeNode(String name) {
        this.name = name;
    }
}

One final note: if using getter and setter methods instead of fields, you will may to add reference annotations on both methods (you will always need them in setters which are used for deserialization; getters for forward references are handled correctly without annotations, but getters for serializing back links do need to be annotated).

Known Issues

(added 25-Sep-2010)

Currently (as of version 1.6.0) combination of abstract types (with polymorphic handling using @JsonTypeInfo) do not work with this feature -- hopefully this can be addressed in future, but there are technical issues that make fix non-trivial. Specific problem is that of deserializer for such types being AbstractDeserializer, which is just a placeholder for real deserializer.

There are some useful articles that show how to use this feature:

* Jackson to the Rescue (with Spring 3.0)


CategoryJackson

JacksonFeatureBiDirReferences (last edited 2010-10-21 00:39:50 by TatuSaloranta)

Copyright ©2009 FasterXML, LLC