com.fasterxml.jackson.databind.JsonMappingException not able to construct instance of class

Viewed 846
import javax.ws.rs.core.Response;

class A{
    @JsonProperty("B")
    List<B> b;
    @JsonProperty("abc")
    String abc;
}

public abstract class B{
    @JsonProperty("def")
    String def;
}

public class C extends B{
    @JsonProperty("xyz")
    String xyz;
}

json:

{
  "B": [
    {
      "def": "<text1>"
    },
    {
      "def": "<text1>",
      "xyz": "<text2>"
    }
  ],
  "abc": "<text3>"
}

Response has content of above json

A a  = response.readEntity(A.class);

Error:

javax.ws.rs.client.ResponseProcessingException:` Problem with reading the data, class A, ContentType: application/json.
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of B: abstract types either need to be mapped

Is there any way we can create an instance of class which contain object of an abstract class?

2 Answers

Because class B is an abstract class you need to provide type which can be used to instantiate B type. In your case is class C. You can instruct Jackson to do that by:

@JsonDeserialize(as = C.class)
abstract class B {

or on field level:

@JsonProperty("B")
@JsonDeserialize(contentAs = C.class)
private List<B> b;

This will include class name as JSON property "class".

@JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="class")
public abstract class B {
}

public class C extends B {
  public int x;
}
public class D extends B {
  public String name;
}

public class A {
  public List<B> items;
}
and this could result in serialized JSON like:

{ "items" : [
  { "class":"D", "name":"TXT" },
  { "class":"C", "x":123 }
]}

similar logic can be used for above mentioned problem for that we need to add some additional info in JSON.

Related