Jackson-databind: No subtype information included when serializing list

Created on 18 Nov 2018  路  1Comment  路  Source: FasterXML/jackson-databind

@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.

Most helpful comment

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:

  1. Sub-class List as class MyTypeList extends ArrayList<SuperType> { }
  2. Force type information via ObjectWriter:

    mapper.writerFor(new TypeReference>() { })
    .writeValueAsString(myObjects);

>All comments

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:

  1. Sub-class List as class MyTypeList extends ArrayList<SuperType> { }
  2. Force type information via ObjectWriter:

    mapper.writerFor(new TypeReference>() { })
    .writeValueAsString(myObjects);

Was this page helpful?
0 / 5 - 0 ratings