I am using Jackson and I'm having problems, when I try to deserialize an Object I get the following error:
com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of net.MyAbstractClass,
problem: abstract types either need to be mapped to concrete types,
have custom deserializer, or be instantiated with additional type information
I am having problems in the attribute:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "@id")
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@ManyToOne
private MyAbstractClass object;
Could anyone help me?
For me there was no default constructor defined for the POJOs I was trying to use. creating default constructor fixed it.
public class TeamCode {
@Expose
private String value;
public String getValue() {
return value;
}
**public TeamCode() {
}**
public TeamCode(String value) {
this.value = value;
}
@Override
public String toString() {
return "TeamCode{" +
"value='" + value + '\'' +
'}';
}
public void setValue(String value) {
this.value = value;
}
}
Your @JsonSubTypes
declaration does not make sense: it needs to list implementation (sub-) classes, NOT the class itself (which would be pointless). So you need to modify that entry to list sub-class(es) there are; or use some other mechanism to register sub-classes (SimpleModule
has something like addAbstractTypeMapping
).
You need to use a concrete class and not an Abstract class while deserializing. if the Abstract class has several implementations then, in that case, you can use it as below-
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@Type(value = Bike.class, name = "bike"),
@Type(value = Auto.class, name = "auto"),
@Type(value = Car.class, name = "car")
})
public abstract class Vehicle {
// fields, constructors, getters, setters
}
In your concrete example the problem is that you don't use this construct correctly:
@JsonSubTypes({ @JsonSubTypes.Type(value = MyAbstractClass.class, name = "MyAbstractClass") })
@JsonSubTypes.Type
should contain the actual non-abstract subtypes of your abstract class.
Therefore if you have:
abstract class Parent
and the concrete subclasses
Ch1 extends Parent
and
Ch2 extends Parent
Then your annotation should look like:
@JsonSubTypes({
@JsonSubTypes.Type(value = Ch1.class, name = "ch1"),
@JsonSubTypes.Type(value = Ch2.class, name = "ch2")
})
Here name
should match the value of your 'discriminator':
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.WRAPPER_OBJECT,
property = "type")
in the property
field, here it is equal to type
. So type
will be the key and the value you set in name
will be the value.
Therefore, when the json string comes if it has this form:
{
"type": "ch1",
"other":"fields"
}
Jackson will automatically convert this to a Ch1
class.
If you send this:
{
"type": "ch2",
"other":"fields"
}
You would get a Ch2
instance.
Source: Stackoverflow.com