I have an object called Animal with two subclasses, Monkey and Lion, I used JsonTypeInfo to support subtype detection, and I suppose on serializing JsonTypeInfo should automatically put property called 'type' depending on the class.
Animal Class
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Lion.class, name = "Lion"),
@JsonSubTypes.Type(value = Monkey.class, name = "Monkey")
})
public class Animal implements Serializable {
String name;
public Animal(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Animal other = (Animal) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Lion Class
public class Lion extends Animal{
public Lion(String name) {
super(name);
}
}
Monkey Class
public class Monkey extends Animal{
public Monkey(String name) {
super(name);
}
}
Main Function
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
Map<String,Animal> animals = new HashMap<String, Animal>();
animals.put("Bob", new Lion("Bob"));
animals.put("Alice", new Monkey("Alice"));
StringWriter sw = new StringWriter();
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.writeValue(sw, animals);
String animlasStr = sw.toString();
Map<String,Animal> dAnimalMap = mapper.readValue(animlasStr, new TypeReference<Map<String, Animal>>() {});
assert dAnimalMap.get("Alice") instanceof Monkey;
}
But when I am deserializing a map of animals it is not working!!, It throws the following exception, the type property is missing.
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id (for class ....Animal)
at [Source: {"Bob":{"name":"Bob"},"Alice":{"name":"Alice"}}
I tried to both type referencing and visible property, I got the same results.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type" , visible =true)