'Jackson custom deserializer module to abstract class

I have a big set of classes (like more that 100) and they are all extend from some abstract class, let's call it ParentClass. Let's call child classes ChildA,ChildB, etc. How can I register custom deserializer for all children and get class type inside my Deserializer? I tried:

module.addDeserializer(ParentClass.class, new MyObjectDeserializer());

but it does not work.

I want to skip doing (what is working):

module.addDeserializer(ChildA.class, new MyObjectDeserializer(ChildA.class));
module.addDeserializer(ChildB.class, new MyObjectDeserializer(ChildB.class));
module.addDeserializer(ChildC.class, new MyObjectDeserializer(ChildC.class));
//etc......

Class type should be known, as I am use Jackson for spring @RequestBody method, what have defined class name there. Any ideas how this can be done?



Solution 1:[1]

As far as I know, I don't think there is a mechanism in jackson that will address your exact needs.

However, there are a couple alternatives you can try. Deserializing polymorphic types with Jackson describes one such alternative, however, you would still need to explicitly define all of the supported subtypes.

Another alternative that would not require you to explicitly define deserialization relationships would be to change your class hierarchy from one of inheritance to that of a container.

For example, converting your abstract parent class to a container like so:

public class DataContainer<T> {
  String commonString;
  Integer commonInteger;  

  T subData;
}

Would allow you to simply define in your controller input function as

public String controllerFunction(DataContainer<ClassA> classA);

without a need to define all these subclass deserializations.

Solution 2:[2]

Late to the party but I had a similar problem which I solved by registering a custom Deserializers to my SimpleModule. The code is in Kotlin but it should be easy to port it to Java.

The class itself:

class UseBaseClassSimpleDeserializers(
    private val baseClass: Class<*>,
    private val baseClassDeserializer: JsonDeserializer<*>
) : SimpleDeserializers() {
    @Throws(JsonMappingException::class)
    override fun findBeanDeserializer(
        type: JavaType?,
        config: DeserializationConfig?,
        beanDesc: BeanDescription?
    ): JsonDeserializer<*>? {
        val beanDeserializer = super.findBeanDeserializer(type, config, beanDesc)
        return if (beanDeserializer == null && baseClass.isAssignableFrom(type!!.rawClass)) {
            baseClassDeserializer
        } else {
            beanDeserializer
        }
    }
}

How to register the custom Deserializers class to a SimpleModule:

val simpleModule = SimpleModule()
simpleModule.setDeserializers(UseBaseClassSimpleDeserializers(ParentClass::class.java, ParentClassDeserializer()))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Campi