Add SubType information at runtime using Jackson for polymorphism

I use Jackson to decouple polymorphic types from JSON. I use @JsonTypeInfo , @JsonSubTypes and @JsonTypeName , similar to Example 4, in this post . My question is: tell me, now I need someone else to extend my code and add a third class: public class Duck extends Animal outside the source code base. How can I (or others) add SubType information without changing the source code (annotation) of the public abstract Animal class ?

UPDATE:

I am forced to use @JsonTypeName to resolve POJO version changes. For instance:

 package my.zoo; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Cat.class, name = " my.zoo.cat@1.0 "), @Type(value = Dog.class, name = " my.zoo.dog@1.0 "), @Type(value = Catv2.class, name = " my.zoo.cat@2.0 ")}) public abstract class Animal { ... } @JsonTypeName(" my.zoo.cat@1.0 ") public class Cat extends Animal { ... } @JsonTypeName(" my.zoo.cat@2.0 ") public class Catv2 extends Animal { ... } @JsonTypeName(" my.zoo.dog@1.0 ") public class Dog extends Animal { ... } // in another java package/project package another.zoo; import my.zoo.*; @JsonTypeName(" my.zoo.dog@2.0 ") public class Dogv2 extends Animal { ... } 

Now the problem that I am facing is that I cannot untie JSON with a name like " my.zoo.dog@2.0 " without adding @Type(value = another.zoo.Dogv2.class, name = " my.zoo.Dog@2.0 ")}) to the Animal class. Therefore, it is obviously impossible to do this with the annotation. Is there any way to do this at runtime?

UPDATE 2:

I just found this SO question with the same / similar use case. My concern is that using annotation will not allow people to extend / implement your base class / interface. I would like to still maintain the extensibility of my base class / interface and make sure that my (un) marshalling logic works with future specific types.

+5
source share
2 answers

I ended up using the Reflections library to find the entire subtype of the Animal class and register JsonSubTypes using the mapper.registerSubtypes(Class<?>... classes) method.

+3
source

Do not use @JsonSubTypes . Use @JsonTypeInfo#use with JsonTypeInfo.Id.CLASS to identify types for serialization and deserialization.

 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type") abstract class Animal { /* whatever */ } 

Jackson then saves the fully qualified name for serializing the object and uses it again to determine the target class for deserialization.

You need to make sure that none of the subclasses has a property named type .


You can do this work with @JsonSubTypes , but it includes mixins and is not a very convenient solution.

+2
source

Source: https://habr.com/ru/post/1237371/


All Articles