Dfr
Dfr

Reputation: 4175

Jackson (de)serializing object as its id

Given POJO:

@XmlRootElement
public class Categories implements Serializable {
    private int id;    
    private String name;

    private Categories parent;

    // ....    

}

I'd like to serialize it to following json:

{ id: 1, name: "some name", parent: 5 }

So, main challenge here is to represent parent object as its id. Same thing i want for deserialization.

I scannned rather large Jackson wiki and did not found anything that allowed to accomplish this without writing plethora of custom code. I think this is pretty common task and solution shold be somewhere nearby.

Also it would be nice if solution will allow to customize null value cases.

UPD:

Now trying to use XmlTypeAdapter approch, not happy with it btw, because i need to write TypeAdapter for everyy single type i have and all they going to contain almost the same code:

public class CategoriesTypeAdapter extends XmlAdapter<Integer, Categories> {

    @Inject
    CategoriesFacade dao;

    @Override
    public Categories unmarshal(Integer v) throws Exception {
        return dao.find(v);
    }

    @Override
    public Integer marshal(Categories v) throws Exception {
        return v.getId();
    }
}

Change in Categories.java:

    @XmlJavaTypeAdapter(CategoriesTypeAdapter.class)
    private Categories parent;

UPD1:

And this is also not worked for me, at least deserializing now always return null in place of object, no idea how to debug this : For this JSON:

{ id: 1, name: "test", parent: 5 }

I get parent always null now:

Categories{categoryId=1, name="test", parentId=null}

UPD2:

I found that htere is my fail in tis isssue, just did not setup things propertly, and my web.xml was lacking this entry:

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.neopod.rest</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

Upvotes: 1

Views: 2222

Answers (2)

Ilya
Ilya

Reputation: 29663

Use propery access to field Categories

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Categories implements Serializable {

    @XmlElement
    Integer categoryId;

    @XmlElement
    String name;

    Categories parentId;

    public Integer getCategoryId() {
        return categoryId;
    }

    public String getName() {
        return name;
    }

    @XmlElement
    public Integer getParentId()
    {
        return parentId == null ? null : parentId.getCategoryId();
    }
}

test

Categories c = new Categories();
c.categoryId = 1;
c.name = "name";
Categories c1 = new Categories();
c1.categoryId = 2;
c.parentId = c1;
System.out.println(new ObjectMapper().writeValueAsString(c));  

output

{"categoryId":1,"parentId":2,"name":"name"}  

EDIT:
make two gatters. @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class Categories implements Serializable {

    @XmlElement
    Integer categoryId;

    @XmlElement
    String name;

    Categories parentId;

    public Integer getCategoryId() {
        return categoryId;
    }

    public String getName() {
        return name;
    }  
    public Category getParentId()
    {
        return parentId;
    }

    @XmlElement(name = "parentId")
    Integer getParentIdForJSON()
    {
        return parentId == null ? null : parentId.getCategoryId();
    }  

}

Upvotes: 1

StaxMan
StaxMan

Reputation: 116472

There are two ways that might work, depending on exact semantics.

First is to use annotation pair @JsonManagedReference / @JsonBackReference, where first is used on "forward" property, and second on "backward" reference. In those cases, second property is not included in serialization, but is recovered during deserialization. This works for simple hierarchic objects.

Second is @JsonIdentityInfo (added in 2.0), and it adds support for arbitrary object references, regardless of direction. It works by serialization each Object as-is the first time it is seen; but on later references serializing them as ids. Deserialization restores linkage automatically.

Upvotes: 4

Related Questions