I am trying to convert a JSON file and an abstract class with two subclasses in Java using Jackson. Ideally, I would like to use JSON as follows:
Json document without shell
[ { "type" : "lion", "name" : "Simba", "endangered" : true, "action" : "running" }, { "type" : "elephant", "name" : "Dumbo", "endangered" : false, "table" : [ 1.0, 2.0, 3.0 ] } ]
I annotated the Abstract Animal class, as shown at http://www.studytrails.com/java/json/java-jackson-Serialization-polymorphism.jsp
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Lion.class, name = "lion"), @Type(value = Elephant.class, name = "elephant") }) public abstract class Animal { String name; boolean endangered;
I can successfully read / write it using a wrapper object, but the generated JSON file will contain an additional animals object.
Wrapped JSON Document
{ "animals" : [ { "type" : "lion", "name" : "Simba", "endangered" : true, "action" : "running" }, { "type" : "elephant", "name" : "Dumbo", "endangered" : false, "table" : [ 1.0, 2.0, 3.0 ] } ] }
When I use a simple Java list, I can successfully read from a Json document without a shell , but if I try to write it, the output file will look like this:
output.json
[ { "name" : "Simba", "endangered" : true, "action" : "running" }, { "name" : "Dumbo", "endangered" : false, "table" : [ 1.0, 2.0, 3.0 ] } ]
Java code
// Test reading using raw list JavaType listType = mapper.getTypeFactory() .constructCollectionType(List.class, Animal.class); List<Animal> jsonList = mapper.readValue(new FileInputStream( "demo.json"), listType); jsonDocument = new File(outputFile); // Test writing using raw list mapper.writerWithDefaultPrettyPrinter().writeValue(jsonDocument, jsonList);
Any ideas how I can include type information when serializing objects in JSON?
The full Eclipse project can be found at: https://github.com/nkatsar/json-subclass
EDIT: Simplified Java code to use JavaType instead of TypeReference . GitHub code has also been updated with the right solutions.
EDIT 2: As mentioned in the comments, I ended up using arrays of objects for serialization / deserialization as follows:
// Test reading using array Animal[] jsonArray = mapper.readValue( new FileInputStream(demoFile), Animal[].class); System.out.println("Reading using array:\nObject: " + Arrays.toString(jsonArray)); // Test writing using array outputJson = mapper.writeValueAsString(jsonArray); System.out.println("Writing using array:\nJSON: " + outputJson);