Jackson: @JsonIdentityInfo Object instead of id

2019-06-21 18:28发布

问题:

Is there a way to influence the serialization process with @JsonIdentityInfo so that it inserts the whole object instead of referencing the id?

@Entity
@JsonIdentityInfo(
        generator = ObjectIdGenerators.IntSequenceGenerator.class,
        property = "linkLabel")
public class LinkLabel implements Serializable {
   //...
}

So instead of referencing "otherObj" with id 1, Jackson should include the whole object.

{
    "objects": [{
            "id": 1,
            "otherObj": [{
                    "id": 1,
                    ...
                }, {
                    "id": 3,
                    ...
                }]
        },
            "id": 2,
            "otherObj": [1] <-- referencing otherObj with id 1
    ]
}

like here:

{
    "objects": [{
            "id": 1,
            "otherObj": [{
                    "id": 1,
                    ...
                }, {
                    "id": 3,
                    ...
                }]
        },
            "id": 2,
            "otherObj": [{
                    "id": 1,  <-- desired format, whole object
                    ...
                }]
    ]
}

We have bidirectional references, so @JsonManagedReference and @JsonBackReference doesn't work properly. This behavior is described here (http://wiki.fasterxml.com/JacksonFeatureObjectIdentity).

回答1:

Like said in the comments and from the links, @JsonIdentityInfo and the Jackson Generators doesn't seem to have an option to enable inserting objects instead of ids.

After more research we finally found this: deserialize Jackson object in JavaScript containing JsonIdentityInfo

This was exactly the scenario we had and we are now using JSOG, which is optimized for bidirectional references and it works like a charm on server and client (AngularJS) side.



回答2:

The issue precisely is with how Jackson work serializing the java object to JSON. When we use @JsonIdentityInfo to resolve the issue of cyclic dependency in object graph, we are forcing the serialization mechanism to serialize the first occurrence of Java object in JSON and the subsequent occurrence to be substituted by the id generated.

The determining factor when to create JSON for Java object is based on access made to the memory location where the JAVA Objects are created.

So, one good way to trick the serialization mechanism would be to create a copy of the child object and then set it. This way the same child object belonging to different parent in collection are treated as different child object instances.

One great way to create an exact copy of the object is using SerializationUtils.serialize/desrialize method.

    byte[] bs= SerializationUtils.serialize(classObject);
    ClassObject cloneEntity = (ClassObject ) SerializationUtils.deserialize(bs);

This creates an exact copy of the an object in different memory relocation.