Can Jackson deserialize to a concrete subsclass using a boolean JSON property it didn't write?

M_M :

I'm using Jackson to deserialize a JSON file received from elsewhere - that is to say I have control over the deserialization, but not the serialization.

Let's say the JSON describes a flat list with a mixture of aquatic and land-based animals.

One of the animal JSON properties is the boolean isAquatic. In Java, AquaticAnimal and LandAnimal are separate classes, each subclasses of the abstract class Animal, which contains member data relevant to both subtypes of animal. Animal has no other subclasses, and never will have. Aquatic animals have properties like gills that make no sense to a LandAnimal (and thus a LandAnimal will never have such a property in the JSON, and the subclass provides associated behaviour). Likewise, the same is true in inverse for land animals, which may have paws, lungs etc. (It's not a perfect example, but it serves its purpose)

When deserializing, I want to use the value of isAquatic to decide which subclass to use when I do the following:

Animal animal = mapper.readValue( ... , Animal.class);

All examples of dealing with polymorphism have involved writing extra data into the JSON when serializing it with Jackson, but I'm only reading in the data, so I can't do this easily. However, I can determine the correct class from information already in the JSON, so I'd like to do that.

I don't fully understand the Jackson tags, but based on other examples, I'd like to be able to do something like this:

@JsonSubTypes({
    @JsonSubTypes.Type(value = LandAnimal.class, isAquatic = false),

    @JsonSubTypes.Type(value = AquaticAnimal.class, isAquatic = true) }
)
public abstract class Animal {
    ...

I'm sure this isn't how that annotation is meant to be used, but hopefully it explains what I'm trying to do.

Can anyone tell me whether Jackson can do this, and if so, how?

locus2k :

It is possible with some nice handy dandy notation work:

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "isAquatic")
@JsonSubTypes({
    @JsonSubTypes.Type(value = LandAnimal.class, name = "false"),
    @JsonSubTypes.Type(value = AquaticAnimal.class, name = "true") 
})
public abstract class Animal {
    private String isAquatic;
    ...

this will take you property isAquatic and mape it to the json type field name and then return the proper class depending on what that name is;

NOTE: I've only done this approach with fields that are Strings thus the reason why i made isAquatic a String, you might be able to try other approaches to see if it works with booleans.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=359035&siteId=1