Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jackson de-serializing polymorphic types

I have got the following sample class:

class Zoo {
    public Collection<? extends Animal> animals;
}

When serializing, I am trying to serialize as much as type information as I can by doing:

  mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

And I get the following JSON:

[
    "com.bp.samples.json.generics.Zoo",
    {
        "animals": [
            "java.util.ArrayList",
            [
                [
                    "com.bp.samples.json.generics.Bird",
                    {
                        "name": "bird-1",
                        "wingSpan": "6 feets",
                        "preferredFood": "food-1"
                    }
                ],
                [
                    "com.bp.samples.json.generics.Cat",
                    {
                        "name": "cat-1",
                        "favoriteToy": "toy-1"
                    }
                ],
                [
                    "com.bp.samples.json.generics.Dog",
                    {
                        "name": "dog-1",
                        "breed": "bread-1",
                        "leashColor": "black"
                    }
                ]
            ]
        ]
    }
]

When it comes to de-serializing, trying to do:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), Zoo.class);

results in the following exception:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: 
Can not deserialize instance of com.bp.samples.json.generics.Zoo out of START_ARRAY toke

and trying to do:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), 
   new TypeReference<Collection<? extends Animal>>() {});

results in:

Can not construct instance of com.bp.samples.json.generics.Animal, 
problem: abstract types either need to be mapped to concrete types, have custom 
deserializer, or be instantiated with additional type information
at [Source: ./DataFiles/Zoo-2.json; line: 2, column: 5]

Writing a custom de-serializer, off course, solves the problem, but is there away to de-serialize without a custom de-serializer?

Thanks, Behzad

like image 224
Behzad Pirvali Avatar asked Jan 31 '26 11:01

Behzad Pirvali


2 Answers

Your first attempt should work as far as I can see. The only explanation I can think of would be that you are trying to use differently configured ObjectMapper for deserialization: both MUST have default typing enabled in the same way (since this is what controls whether type information is included or not).

If you are using the same mapper instance (or identically configured), you may want to file a bug report so the problem gets diagnosed and fixed.

like image 113
StaxMan Avatar answered Feb 02 '26 00:02

StaxMan


Make sur that you enabled type informations for the ObjectMapper instance you use to deserialize. You want to deserialize to Zoo not to Collection of Animals, so the first code snipet is right.

You might also want to try Genson lib. I just checked your example with it, and everything seems to work fine. To enable polymorphic types support in Genson you need to configure your genson instance:

Genson genson = new Genson.Builder().setWithClassMetadata(true).create();
like image 38
eugen Avatar answered Feb 02 '26 00:02

eugen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!