Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@JsonIdentityReference not working with collections #138

Closed
airborn opened this issue Jan 4, 2013 · 10 comments
Closed

@JsonIdentityReference not working with collections #138

airborn opened this issue Jan 4, 2013 · 10 comments

Comments

@airborn
Copy link
Contributor

airborn commented Jan 4, 2013

I've got two simple POJO's and a test resource. The problem is that whole ObjGroup.objs are being serialized instead of just id. Everything works as expected if I change objs type from Set<Obj> to Obj[]

package pl.airborn.json;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Obj {

    private int id;
    private String name;
    @JsonIdentityReference(alwaysAsId = true)
    private ObjGroup objGroup;

    public Obj(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ObjGroup getObjGroup() {
        return objGroup;
    }

    public void setObjGroup(ObjGroup objGroup) {
        this.objGroup = objGroup;
    }
}
package pl.airborn.json;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import java.util.HashSet;
import java.util.Set;

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ObjGroup {

    private int id;
    private String name;
    @JsonIdentityReference(alwaysAsId = true)
    private Set<Obj> objs = new HashSet<>();

    public ObjGroup(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Obj> getObjs() {
        return objs;
    }

    public void setObjs(Set<Obj> objs) {
        this.objs = objs;
    }
}
package pl.airborn.json;

import com.google.inject.Singleton;
import com.nowatel.map.mapserver.Obj;
import com.nowatel.map.mapserver.ObjGroup;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/test")
@Singleton
@Produces(MediaType.APPLICATION_JSON)
public class TestResource {

    @GET
    public Response fail() {
        Obj o1 = new Obj(1, "name 1");
        Obj o2 = new Obj(2, "name 2");
        ObjGroup og = new ObjGroup(1, "group");

        og.getObjs().add(o1);
        og.getObjs().add(o2);

        o1.setObjGroup(og);
        o2.setObjGroup(og);

        return Response.ok(og).build();
    }
}
@cowtowncoder
Copy link
Member

Quick note: Object ids only work for POJOs, and not for Collections (or anything serialized as JSON Arrays, such as arrays) or Maps. Not sure if this is causing problems, but at least annotation on Set property is unnecessary.

This limitation is due to practical problems in trying to figure out how to store identity information for Collections, and not a fundamental limitation. However, there are no concrete plans to support identity of collections at this point.

@airborn
Copy link
Contributor Author

airborn commented Jan 4, 2013

Contrary to what you say, it works for me if I return an array. Is this is by accident?

@JsonIdentityReference(alwaysAsId = true)
private Obj[] objs;
{
    "id": 1,
    "name": "group",
    "objs": [
        1,
        2
    ]
}

@cowtowncoder
Copy link
Member

Ah, no, sorry, my explanation was bit vague. Elements of Collections and arrays will be handled as expected; it's just that actual Collection and array objects will not be referencable. So above is as expected.

@airborn
Copy link
Contributor Author

airborn commented Jan 4, 2013

If the above is an expected result and Collections and arrays should be handled the same way then something is probably wrong with handling Collections. Because with Set<Obj> i get different output: (sorry, probably I should attach it yesterday).

{
    "id": 1,
    "name": "group",
    "objs": [
        {
            "id": 1,
            "name": "name 1",
            "objGroup": 1
        },
        {
            "id": 2,
            "name": "name 2",
            "objGroup": 1
        }
    ]
}

@cowtowncoder
Copy link
Member

Ok. Yes, it does sound like there is some difference between serializers there. Thank you for clarifications -- I was missing the actual issue. :)

cowtowncoder added a commit that referenced this issue Jan 10, 2013
Test case for Issue #138 @JsonIdentityReference not working with collections
@airborn
Copy link
Contributor Author

airborn commented Jan 11, 2013

Ok, from whay I can see this will work for collection if ObjectMapper is configured with enable(MapperFeature.USE_STATIC_TYPING);
but it will not work if Collection is annotated with
@JsonSerialize(typing = JsonSerialize.Typing.STATIC)

@cowtowncoder
Copy link
Member

Handling would differ in two cases in that forcing static type allows earlier retrieval of JsonSerializer instances; whereas with dynamic typing serializer typically can only be located during serialization. So code paths will differ.
Things should work in both cases, but latter is probably missing something crucial wrt object id handling.

@cowtowncoder
Copy link
Member

Turns out that this was mostly fixed by patch for #97, so serialization will work with 2.1.4.

But there is the additional test for deserialization, and that will fail. I am not quite as sure as to what to do with it -- the issue is that there is no real way to resolve Object Id externally. One possibility is to just do bare-bones "stick Object Id in there and hope for best" (which only works for Property Id inclusion); I think I will see if that could work.
Longer term there should be a way to hook in external id resolver for deserialization; I will file an RFE.

@cowtowncoder
Copy link
Member

Since #176 is finally implemented, this issue should be resolved. Although not sure what to do with one still failing unit test.

@cowtowncoder
Copy link
Member

Looking at the failing test, it can only be resolved by custom Object Id resolver (or by changing annotations used); so it should be solvable. However, as written, test can't be made to work. So I removed the test; we should have actual tests for custom Object Id resolver elsewhere.

christophercurrie pushed a commit to christophercurrie/jackson-databind that referenced this issue Jul 19, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants