Polymorphic JSON Deserialization with Jackson

March 19, 2025

JAVA
JSON
VIEWS: 36COMMENTS: 0

Recently, in one of the projects I’m involved in, we faced an interesting technical challenge related to JSON deserialization using the Jackson library. The scenario involved the need to receive a raw JSON and map its data into a Java class structure in a flexible and dynamic way. Specifically, we needed a solution where a JSON could be initially mapped to a standard class “X” that contained all the common properties between two distinct classes “Y” and “Z”. The complexity arose when we realized that after the initial deserialization, we needed to decide, based on the first two digits of a given property, which of the specialized classes the JSON should be mapped to. Furthermore, it was crucial that common properties were kept in the default class (X), while new properties were added to the appropriate subsequent class (Y and Z).

Given this demand, a simple and effective solution with Jackson was not evident, especially considering that we did not want to rely on explicit type metadata in JSON (such as the @JsonTypeInfo annotation). Therefore, we chose to implement a custom deserializer to handle this conditional logic in a robust and reusable way.

Let me introduce the following exemple:

Imagine we have the following class Vehicle:

Java

And the child classes Bike:

Java

And Car:

Java

The custom desserializer:

Java

  • If the nested class is not static, Jackson may have difficulty instantiating it, generating errors or unexpected behavior such as NoClassDefFoundError or IllegalArgumentException.

First, the custom deserialize method converts the JsonParser into an ObjectMapper, which is the primary tool for reading and writing JSON objects in Java. The JSON is then read as a tree of nodes (ObjectNode), allowing direct access to the JSON fields. So we can apply our logic to validate which path we will follow…

The treeToValue method of Jackson’s ObjectMapper class is used to convert a JSON tree node (an object of type JsonNode) into an instance of a specified Java class, that is, if the root JsonNode contains JSON data compatible with the Car or Bike class, the treeToValue method will create an instance of one of that classes with that data.

A common problem…

When implementing this deserialization logic, one challenge was to avoid infinite loops during the deserialization process. This problem can occur especially when Jackson tries to resolve subtypes recursively. If not handled properly, this behavior can lead to a stack StackOverflowError, stopping the program from executing. That can be achieved by the use of the None class in the child classes. The None class is a convention within Jackson to indicate that no special action should be taken during deserialization.:

Java

This ensures that the deserializer does not attempt to deserialize again an already deserialized class. As the abstract class already (and only) points to our custom deserializer.

And so we solved a challenge we faced in deserializing JSON in a polymorphic way. If anyone has solved this problem in a different way, I’d love to hear about it.

DISCUSSION.LOG

No comments yet. Be the first to comment!

ADD_COMMENT

© 2025 BITWISEOPS BLOG - All rights reserved