πŸ“œJackson Modules

How to serialize Result objects with Jackson 2.x and 3.x

When using Result objects with Jackson we might run into some problems. The Jackson datatype modules for Result solve them by making Jackson treat results as if they were ordinary objects.

Jackson is a Java library for JSON parsing and generation. It is widely used for converting Java objects to JSON and vice versa, making it essential for handling data in web services and RESTful APIs.

How to Use These Add-Ons

Choose the Maven dependency that matches your Jackson version.

Jackson 2.x

Add this Maven dependency to your build:

Group ID
Artifact ID
Latest Version

com.leakyabstractions

result-jackson

Jackson 3.x

Add this one instead:

Group ID
Artifact ID
Latest Version

com.leakyabstractions

result-jackson3

Test Scenario

Let's start by creating a class ApiResponse containing one ordinary and one Result field.

Problem Overview

Then we will take a look at what happens when we try to serialize and deserialize ApiResponse objects.

Serialization Problem (Jackson 2.x Only)

Now, let's instantiate an ApiResponse object.

And finally, let's try serializing it using an object mapper.

With Jackson 2.x, this will produce an error: InvalidDefinitionException.

The reason is Jackson encounters Optional values internally and it will not handle it unless you register the appropriate modules.

Deserialization Problem (Both Jackson 2.x and 3.x)

Now, let's reverse our previous example, this time trying to deserialize a JSON object into an ApiResponse.

This will produce an error: InvalidDefinitionException. Let's inspect the stack trace.

This behavior again makes sense. Essentially, Jackson cannot create new result objects because Result is an interface, not a concrete type.

Solution Implementation

The Jackson datatype modules for Result provide serializers and deserializers so that Jackson treats results as if they were regular objects.

Registering the Jackson Datatype Module for Result

First of all, we need to add the the appropriate datatype module as a dependency.

Jackson 2.x

Then, all we need to do is register ResultModule with our object mapper.

Alternatively, you can also make Jackson 2.x auto-discover the module.

Jackson 3.x

Just like the previous example, we need to add ResultModule to our JSON mapper.

Or simply use auto-discovery:

Regardless of the chosen registration mechanism, once the appropriate dataype module is registered all functionality is available for all normal Jackson operations.

Serializing Results

Now, let's try and serialize our ApiResponse object again:

If we look at the serialized response, we'll see that this time the result field contains a null failure value and a non-null success value:

Next, we can try serializing a failed result.

We can verify that the serialized response contains a non-null failure value and a null success value.

Deserializing Results

Now, let's repeat our tests for deserialization. If we read our ApiResponse again, we'll see that we no longer get an InvalidDefinitionException.

Finally, let's repeat the test again, this time with a failed result. We'll see that yet again we don't get an exception, and in fact, have a failed result.

Conclusion

We learned how to serialize and deserialize Result objects using both Jackson 2.x and Jackson 2.x, demonstrating how the provided datatype module enables Jackson to treat Results as ordinary objects.

The integration is nearly identical across versions; the main differences are limited to dependency coordinates and how the object mapper is constructed and configured.

Last updated

Was this helpful?