Reputation: 7364
I've got following classes :
public class City
{
Zoo zoo;
}
public class Zoo
{
Animal[] animals;
}
public abstract class Animal
{
String name;
abstract void eat();
}
I want to deserialize an instance of City
class with Jackson. Howerer, since Animal
is an abstract type, I've got following exception:
Could not read JSON: Can not construct instance of Animal, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
How to map Animal
to concrete type?
The problem is that I am able to modify only City
class.
Upvotes: 1
Views: 2084
Reputation: 116472
For one-to-one (abstract/impl) use case, registering sub-classes (which you can do via ObjectMapper.registerSubtypes(...)
, or using SimpleModule
) is an alternative to annotations.
But if you have truly polymorphic type, @JsonTypeInfo
annotation is the key. It needs to be added in the base class that is used static type (like Animal
), and will result in addition of a Type Identifier on serialization, and use of that id on deserialization.
There are multiple choices both for kind of type id (class name vs logical name) as well as inclusion style (as property, as wrapper array, as wrapper object, as external property).
Upvotes: 2
Reputation: 8889
Since you can modify only the City
class, you may find mix-in annotations useful. The idea is you create and annotate a a new class that acts as a surrogate for the class you wish you could annotate (but can't for whatever reason). Then you register your surrogate with Jackson, telling it to look for annotations on your surrogate instead of the actual class.
To start with, you could try creating a mix-in for Animal
and annotating the mix-in class with @JsonDeserialize(as=ConcreteClass.class)
as Vince Emigh suggested. Once you've got that working, you can try annotating it with polymorphic type handling annotations.
Upvotes: 2