Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing field when deserializing using Jackson (Polymorphic)

Tags:

java

jackson

I am trying to create an java SDK for a front-end library that takes JSON input. Essentially, this SDK converts objects of certain type into JSON which is then consumed by that front-end library.

I am using jackson's polymorphic serialization/deserialization using its annotation system.

I have a base class A and 2 child classes B and C extending A. Class A has a type field, using which I decide what class (B or C) is to be used. The syntax looks something like this:

@JsonTypeInfo({
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.EXISTING_PROPERTY,
  property= "type"
})
@JsonSubTypes({
  @JsonSubTypes.Type(value = B.class, name = "b"),
  @JsonSubTypes.Type(value = C.class, name = "c")
})
public class A {
  private String type;

  public void setType(String type){
    this.type = type;
  }

  public String getType(){
    return this.type;
  }
}

public class B extends A {

}

public class C extends A {

}

So now, when I use Jackson's ObjectMapper's readValue function and read the stringified JSON and convert to class A, I get the correct instance of either class A or class B based on the value of the type variable. However, and here is the actual problem, when I try to use the function getType I always get null in those objects. I am not sure why jackson is not setting those values on the object.

String json = "{ type: 'b' }"; // example input json

ObjectMapper om = new ObjectMapper();
A a = om.readValue(json, A.class);
// a is actually an instance of class B

a.getType()// this is null
like image 462
Rajan Avatar asked Oct 17 '16 06:10

Rajan


1 Answers

You need to add to @JsonTypeInfo the parameter visible = true to avoid to remove the type when deserializing.

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.EXISTING_PROPERTY,
  property= "type",
  visible = true
)

public abstract boolean visible() default false

Property that defines whether type identifier value will be passed as part of JSON stream to deserializer (true), or handled and removed by TypeDeserializer (false). Property has no effect on serialization. Default value is false, meaning that Jackson handles and removes the type identifier from JSON content that is passed to JsonDeserializer.

like image 193
Franjavi Avatar answered Sep 28 '22 08:09

Franjavi