[Solved] com.fasterxml.jackson.databind.exc. InvalidDefinitionException: Cannot construct instance of `XYZ` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

InvalidDefinitionException is an intermediate exception which is used as the base class for all JsonMappingExceptions that occurred due to problems with target type definition. Generally a problem with properties or annotations used on a class.

Example of InvalidDefinitionException

Here Publication class is abstract that’s causing issues because we can’t directly create an instance of an abstract class. Here at the time  of JSON deserialization to author object not able to create an instance of Publication class.

public class Author {
	  private String name;
	  public Publication publication;

	  public Author()
	  {

	  }

	  //getter and setter of properties
	}

	public abstract class Publication {
	public String title;

	public Publication() {

	}
	// getter and setter of properties
}
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
<span id="mce_SELREST_start" style="overflow: hidden; line-height: 0;"></span>
public abstract class Publication {
	public String title;

	public Publication() {

	}
	// getter and setter of properties
}
import java.io.IOException;

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestJacksonExample {

public static void main(String[] args) {
String json = "{\"name\":\"Saurabh Gupta\",\"publication\":{\"title\":\"Facing Issues On IT\",\"type\":\"Drama\" }}";

try
{
   ObjectMapper mapper = new ObjectMapper();
   Author author= mapper.readValue(json, Author.class);
   System.out.println(author);
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}

Stacktrace of InvalidDefinitionException


com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.fiot.json.jackson.exceptions.Publication` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{"name":"Saurabh Gupta","publication":{"title":"Facing Issues On IT"}}"; line: 1, column: 39] (through reference chain: com.fiot.json.jackson.exceptions.Author["publication"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
    at com.fiot.json.jackson.exceptions.TestJacksonExample.main(TestJacksonExample.java:17)

Solutions

As a solution to the current issue, Not declare Publication class as abstract because we can’t directly create an instance of an abstract class only allowed instance through subclass. 

Recommend Solution

We can solve this problem by using simple @JsonDeserialize on the abstract class as mentioned as a subtype.

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

//@JsonDeserialize(as = Book.class)
public abstract class Publication {
	public String title;

	public Publication() {

	}
	// getter and setter of class
}

If abstract class having more than one subtype, then mentioned all the classes as SubTypes.

@JsonSubTypes(
{
	@Type(value = Book.class, name = "book"),
	@Type(value = Magzine.class, name = "magzine"),
        @Type(value = Comics.class, name = "comics")
})
public abstract class Publication {
}

Note:

Jackson looks for POJO class for deserialization. As per the definition of POJO (Plain Old Java Object) is the class without any restriction, having getter and setter methods, if required can also implement object class methods like equals, toString(), etc.

References

https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/exc/InvalidDefinitionException.html

You would like to see

Follow below link to learn more on JSON and  JSON issues solutions: