@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = SubType1.class, name = "SubType1"),
@Type(value = SubType2.class, name = "SubType2"),
})
public abstract class SuperType {
...
}
public class SubType1 {
...
}
public class SubType2 {
...
}
private ObjectMapper mapper = new ObjectMapper();
List<SuperType> objects = new ArrayList<>();
objects.add(new SubType1(...));
objects.add(new SubType2(...));
System.out.println(mapper.writeValueAsString(objects));
I expect the output to be a JSON array with 2 JSON objects including the type property but that is not the case. Therefore, deserialization doesn't work. If I pass an object instead of a list, it works, for example:
public class MyObjects {
private List<SuperType> objects;
public List<SuperType> getObjects() {
return objects;
}
public MyObjects(List<SuperType> objects) {
this.objects = objects;
}
}
List<SuperType> objects = new ArrayList<>();
objects.add(new SubType1(...));
objects.add(new SubType2(...));
MyObjects myObjects = new MyObjects(objects);
System.out.println(mapper.writeValueAsString(myObjects));
I'm using Jackson v2.9.7.
This is Java Type Erasure in action: type information for List, as root value, is always only List<?>. This is why I recommend against using generic types as root value -- it'd work fine as a property of a POJO.
There are 2 workarounds:
List as class MyTypeList extends ArrayList<SuperType> { }Force type information via ObjectWriter:
mapper.writerFor(new TypeReference>() { })
.writeValueAsString(myObjects);
Most helpful comment
This is Java Type Erasure in action: type information for
List, as root value, is always onlyList<?>. This is why I recommend against using generic types as root value -- it'd work fine as a property of a POJO.There are 2 workarounds:
Listasclass MyTypeList extends ArrayList<SuperType> { }Force type information via
ObjectWriter:mapper.writerFor(new TypeReference
>() { })
.writeValueAsString(myObjects);