Jon Driscoll Jon Driscoll - 1 year ago 93
JSON Question

Deserialize JSON with Jackson into Polymorphic Types - A Complete Example is giving me a compile error

I am attempting to work through a tutorial from Programmer Bruce that is supposed to allow the deserialization of polymorphic JSON.

The complete list can be found here
Programmer Bruce tutorials (Great stuff btw)

I have worked through the first five with no problems but I have hit a snag on the last one (Example 6), which of course is the one I really need to get working.

I am getting the following error at compile time

The method readValue(JsonParser, Class) in the type ObjectMapper is not applicable for the arguments (ObjectNode, Class)

and it's being caused by the chunk of code

public Animal deserialize(
JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends Animal> animalClass = null;
Iterator<Entry<String, JsonNode>> elementsIterator =
while (elementsIterator.hasNext())
Entry<String, JsonNode>;
String name = element.getKey();
if (registry.containsKey(name))
animalClass = registry.get(name);
if (animalClass == null) return null;
return mapper.readValue(root, animalClass);

Specifically by the line

return mapper.readValue(root, animalClass);

Has anyone run into this before and if so, was there a solution?

I'd appreciate any help anyone can give
Thanks in advance
Jon D.

Answer Source

As promised, I'm putting an example for how to use annotations to serialize/deserialize polymorphic objects, I based this example in the Animal class from the tutorial you were reading.

First of all your Animal class with the Json Annotations for the subclasses.

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
    @JsonSubTypes.Type(value = Dog.class, name = "Dog"),

    @JsonSubTypes.Type(value = Cat.class, name = "Cat") }
public abstract class Animal {

    private String name;

    public String getName() {
        return name;

    public void setName(String name) { = name;


Then your subclasses, Dog and Cat.

public class Dog extends Animal {

    private String breed;

    public Dog() {


    public Dog(String name, String breed) {

    public String getBreed() {
        return breed;

    public void setBreed(String breed) {
        this.breed = breed;

public class Cat extends Animal {

    public String getFavoriteToy() {
        return favoriteToy;

    public Cat() {}

    public Cat(String name, String favoriteToy) {

    public void setFavoriteToy(String favoriteToy) {
        this.favoriteToy = favoriteToy;

    private String favoriteToy;


As you can see, there is nothing special for Cat and Dog, the only one that know about them is the abstract class Animal, so when deserializing, you'll target to Animal and the ObjectMapper will return the actual instance as you can see in the following test:

public class Test {

    public static void main(String[] args) {

        ObjectMapper objectMapper = new ObjectMapper();

        Animal myDog = new Dog("ruffus","english shepherd");

        Animal myCat = new Cat("goya", "mice");

        try {
            String dogJson = objectMapper.writeValueAsString(myDog);


            Animal deserializedDog = objectMapper.readValue(dogJson, Animal.class);

            System.out.println("Deserialized dogJson Class: " + deserializedDog.getClass().getSimpleName());

            String catJson = objectMapper.writeValueAsString(myCat);

            Animal deseriliazedCat = objectMapper.readValue(catJson, Animal.class);

            System.out.println("Deserialized catJson Class: " + deseriliazedCat.getClass().getSimpleName());

        } catch (Exception e) {


Output after running the Test class:

{"@type":"Dog","name":"ruffus","breed":"english shepherd"}

Deserialized dogJson Class: Dog


Deserialized catJson Class: Cat

Hope this helps,

Jose Luis