Akshay Sharma
Akshay Sharma

Reputation: 49

Jackson does not include type info for fields while serialization

I am trying to serialize an object to json using jackson 2.6.3 I want to include type info in the serialized json. This does not work for members nested within this class.

Here is the test code.

public class Test {

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {

}
@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteA implements A {

}

@JsonSubTypes({ @JsonSubTypes.Type(value = ConcreteB.class)})
interface B {

}
@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS)
class ConcreteB implements B {
    A a;
    public A getA() {
        return a=new ConcreteA();
    }
}

@org.junit.Test
public void testSerialisation() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    System.out.println(objectMapper.writeValueAsString(new ConcreteB()));
}
}

The json being converted by jackson is

{"@class":"Test$ConcreteB","a":{}}

Note that it does not include type info for field 'a'. The type info does get included while serializing just A.

{"@class":"Test$ConcreteA"} 

UPDATE: Here is the explanation and solution from jackson dev for the problem https://github.com/FasterXML/jackson-databind/issues/1015

Upvotes: 4

Views: 10810

Answers (3)

Vladimir Stanciu
Vladimir Stanciu

Reputation: 1536

You also have to set the visible property to true, otherwise it might still not work(my case). I will enhance one of the above answers:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "@class",
        visible = true)
@JsonSubTypes({
        @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {
}

Upvotes: 1

NIrav Modi
NIrav Modi

Reputation: 6962

I have faced the same issue. I had imported wrong ObjectMapper class.

Ideally, it should be jackson-databind.jar

com.fasterxml.jackson.databind.ObjectMapper

but I have imported jackson-mapper-asl.jar

org.codehaus.jackson.map.ObjectMapper

Upvotes: 0

jbarrueta
jbarrueta

Reputation: 5175

It seems you were pretty close, all you need to add is a way to tell jackson how to handle your interface type.

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "@class")
@JsonSubTypes({
        @JsonSubTypes.Type(value = ConcreteA.class)})
interface A {
}

So adding the @JsonTypeInfo to your interface will add the type information in a property you can configure to be the one you expect, in this case I chose @class.

The Json output I got from my example:

{"@class":"com.company.jackson.Test$ConcreteB","a":{"@type":"Test$ConcreteA"}}

Hope it helps,

José Luis

Upvotes: 6

Related Questions