Polymorphic deserialization - @JsonTypeInfo “defaultImpl” for collections

1,694 views
Skip to first unread message

Jothisubaramaniam P

unread,
Mar 6, 2017, 1:10:33 PM3/6/17
to jackson-user

There is one set of definition as follows:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "type",
        visible = true)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Dog.class, name = "dog"),
        @JsonSubTypes.Type(value = Cat.class, name = "cat")})  
public abstract class Animal implements Serializable{

    AnimalType type;

}

public class Dog extends Animal { AnimalType type = new AnimalType("dog"); }
public class Cat extends Animal { AnimalType type = new AnimalType("cat"); }

There is another set of definition as follows:

    public class Pets
    {
        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Dog.class)
        Doggies doggies;

        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Cat.class)
        Kitties kitties;

public static class Doggies extends ArrayList<Dog> {

    }

    public static class Kitties extends ArrayList<Cat>{

    }
    }

The actual data on the wire is as follows(the important thing is it does NOT have a "type" field but otherwise is json compatible with Dog/Cat types):

{
    "doggies": [
    ]
    "kitties": [
    ]   
}

I tried to use RestTemplate to receive the data:

restTemplate.exchange(....Pets.class);

It worked! But the question is - is it working out of chance? or is it the right approach to Jackson? Hoping that some jackson expert would confirm if this is a proper way to proceed (and not working out of chance).

The reason I ask this question is - how does Jackson make use of 'defaultImpl'? It is working on an array at the time but somehow takes the suggestion of "defaultImpl" to be used on the array element (rather than the array itself)?

Jothisubaramaniam P

unread,
Mar 6, 2017, 1:10:33 PM3/6/17
to jackson-user

The reason I ask this question is - how does Jackson make use of 'defaultImpl'? It is working on an array at the time but somehow takes the suggestion of "defaultImpl" to be used on the array element (rather than the array itself)?


Tatu Saloranta

unread,
Mar 6, 2017, 7:44:56 PM3/6/17
to jackson-user
Ok, pertinent points are:

1. @JsonTypeInfo can be used both on classes (types) and properties;
annotation on property overrides one in class
2. When applied on property, @JsonTypeInfo does indeed affect contents
for Lists, arrays and Maps and NOT the container (value) itself

The second part is bit different from some other annotations, where
there is clear(er) distinction between value, content and key
modifiers (like, @JsonDeserialize having "as", "contentAs" and "keyAs"
properties). This was influenced by the way JAXB works, and since it
seemed (at the time) that there is not all that much benefit in having
polymorphic type information for collection/map itself, as that is
mostly compile time fluff in Java.

Also: if your data has literally empty arrays, no elements,
polymorphic type does not matter that much.
But it should still work even if there were elements; they should use
`defaultImpl` from most specific annotation (per-property override).

-+ Tatu +-

Jothisubaramaniam P

unread,
Aug 8, 2017, 2:24:04 PM8/8/17
to jackson-user
Thank you for the answer.

The following also worked. i.e. I removed the explicit supply of type information to the list attributes.
public class Pets
    {
        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME
, defaultImpl = Dog.class)
        List<Dog> doggies;

        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Cat.class)
        List<Cat> kitties;


    }
As per the details that you have shared, this is also expected to work and the type determination logic will work in this case as well. Is this correct?

Tatu Saloranta

unread,
Aug 9, 2017, 8:09:57 PM8/9/17
to jackson-user
On Tue, Aug 8, 2017 at 11:24 AM, Jothisubaramaniam P <mai...@gmail.com> wrote:
> Thank you for the answer.
>
> The following also worked. i.e. I removed the explicit supply of type
> information to the list attributes.
>
> public class Pets
> {
> @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Dog.class)
> List<Dog> doggies;
>
> @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Cat.class)
> List<Cat> kitties;
>
>
> }
>
> As per the details that you have shared, this is also expected to work and
> the type determination logic will work in this case as well. Is this
> correct?

Yes, that should work.

-+ Tatu +-
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages