Let's say you have some classes coming from another library that you need to serialize into JSON using Jackson. You can't manipulate the source code of these classes one reason or another, and you have a problem:
These classes don't serialize correctly
There are a number of reasons this can happen, but in this post we're going to focus on two examples: two classes that have a recursive relationship to one another, and a class that doesn't conform to the bean spec.
dealing with recursive relationships
Let's say we have two classes,
Thing, as shown below.
User has a one to many relationship with
Thing has a many to one relationship back to its parent,
Given these classes, let's say in a unit test we create users using the following code, establishing the recursive relationship:
Now that we can create a user, let's try serializing:
If you run that method, your test will fail, and you'll see a nice CPU spike on your computer because this just happened:
fixing recursive relationship issues with mixins
As it turns out, Jackson has an awesome feature called mixins that can address this type of problem (remember, we're assuming
Thing are not modifiable).
Mixins allow you to create another class that has additional Jackson annotations for special serialization handling, and Jackson will allow you to map that class to the class you want the annotations to apply to. Let's create a mixin for
Thing that specifies a
Now you might be thinking, "What's that 'thing filter' string referencing?" We have to add this mixin to the object mapper, binding it to the
Thing class, and then we have to create a filter called "thing filter" that exludes
Thing's field of
user, as shown in the test below:
If you run this test, you'll see that it passes.
dealing with a class that doesn't conform to the bean spec
Let's say we have two other classes,
WidgetName. For some reason, the person who wrote
WidgetName decided to not conform to the bean spec, meaning when we serialize an instance of
Widget, we can't see data in
Let's say we're creating widgets using the code below:
If we try to create a widget like this and serialize it, we won't see the name. Here's a test that will serialize:
And here's the output:
fixing classes that don't conform to the bean spec with modules and customer serializers
We can address this problem pretty easily using a Jackson module that provides a custom serializer for
WidgetName. The serializer can be seen below, and it uses the
JsonGenerator instance to write the value from the
We now need to wire this up in order to use it. Below is a test that creates a
SimpleModule instance, wires up our custom serializer to it, and registers the module within our
If you run this test, you can see the correct output for the serialization:
conclusion and resources
All the resources used in this example can be found on Github at https://github.com/theotherian/jackson-mixins-and-modules. If you end up having to serialize data that's outside of your control and is causing you problems, you should be able to get a lot of mileage out of these two solutions.