Using the Jackson Mix-in Annotation

Using the Jackson Mix-in Annotation

6 Comments

Last Updated on October 22, 2024 by jt

Prior to Jackson 1.2, the only way to serialize or deserialize JSON using Jackson was by using one of the following two methods:

  • Adding annotations to modify the POJO classes
  • Writing custom serializers and deserializers

Now imagine you want to serialize or deserialize a 3rd party POJO which you don’t have access to its source code. What would you do?

Also, you might want your code clean and open to other JSON library, such as GSON.

What would you do to decouple your code from Jackson annotations?

Jackson mix-in annotations helps you resolve this kind of problems. These annotations are used in a mix-in class or interface but function as if they were directly included in the target class.

In this post we will look at how to use the Jackson mix-in annotations.

Sample Application

Let us create a simple Spring Boot application to understand how Jackson mix-in annotation works.

Consider you want serialize or deserialize a User POJO in a Spring Boot application.

Here is code of the User POJO.

User.java
public class User {
    private long id;
    private String name;
    private int age;
    private String gender;
    private String email;
    private String phoneNo;

    public User(long id, String name, int age, String gender, String email, String phoneNo) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.email = email;
        this.phoneNo = phoneNo;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", email='" + email + '\'' +
                ", phoneNo=" + phoneNo +
                '}';
    }
}

In the preceding code, User is a typical POJO but is not designed to be used with data binding. The User class doesn’t have the default constructor and neither any getter and setter methods.

Let’s assume that you don’t have access to the source code of the User POJO. Or there is some constraint disallowing you to modify the existing POJO. In this scenario, you can’t serialize or deserialize a User object through annotations or by defining your own custom serializer and deserializer.

Let us see how mix-in annotations can solve this problem.

The Jackson Mix-in Class

For mix-in annotation, you first need to define a mix-in class or interface.

Let’s define an abstract mix-in class for User. Ensure that the mix-in class have a constructor matching the source POJO.

Use the @JsonCreator annotation on the constructor and the @JsonProperty property to specify all the properties of the POJO.

Here is code for the UserMixin Jackson mix-in class.

UserMixin.java
public abstract class UserMixin {
    @JsonCreator
    public UserMixin(@JsonProperty Long id, @JsonProperty String name,
                     @JsonProperty int age, @JsonProperty String gender,
                     @JsonProperty String email, @JsonProperty String phoneNo) {

    }
}

UserMixin is an abstract class where the constructor of the class is annotated with @JsonCreator to tell Jackson in what order to pass fields from a JSON object to the constructor.

Each argument of the constructor is annotated with @JsonProperty to indicate the name of the property to bind to.

After creating the UserMixin class, you must configure the ObjectMapper to use the mix-in for the User POJO, like this.

objectMapper.addMixIn(User.class, UserMixin.class);
String json = objectMapper.writerWithDefaultPrettyPrinter()
               .writeValueAsString(user);

Here is the complete test code to test the Jackson mix-in.

UserTest.java
public class UserTest {
    private User user;

    @Before
    public void setUp(){
        user = new User(123,"James",23,"Male",
                "[email protected]", "1234567890");
    }
    @After
    public void tearDown(){
        user = null;
    }

    @Test
    public void JacksonMixinAnnotationTest() throws JsonProcessingException{
        ObjectMapper objectMapper = buildMapper();
        objectMapper.addMixIn(User.class, UserMixin.class);
        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
        System.out.println(json);

    }

    private static ObjectMapper buildMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibilityChecker(objectMapper.getSerializationConfig()
                .getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
        return objectMapper;
    }

}

As you can see in the code, ObjectMapper is configured in the buildMapper() method.

In the test method, an ObjectMapper is created and the addMixIn() method is called on it. The addMixIn() method configures the association between the mix-in and target classes, to be used during serialization.

Here is the output of the Jackson Mix-in test from IntelliJ:

Jackson Mixin Test Results

Spring Framework 6: Beginner to Guru

Checkout my best selling course on Spring Framework 6. This is the most comprehensive course you will find on Udemy. All things Spring!

About jt

    You May Also Like

    6 comments on “Using the Jackson Mix-in Annotation

    1. January 28, 2019 at 2:39 pm

      Wonderful info. I learned something new 🙂

      Reply
    2. May 30, 2019 at 10:40 pm

      It looks like something is wrong in the code snippet of User.java, UserMixin.java and UserTest.java. All I see is a blank square.

      Reply
      • June 1, 2019 at 1:25 pm

        I had to change the wordpress plugin I use syntax highlighting & am in the process of updating posts. Should be fixed soon!

        Reply
    3. January 20, 2020 at 4:29 pm

      Hi , I have a requirement to parse the Dynamic response json to Java object. For ex, if the input attribute is 2019, then the JSON will have 2019_id. If it is 2020 then 2020_id in json. How to handle this scenario?

      Reply
    4. September 25, 2020 at 9:19 am

      good article.the font is small of website. it will be better to be bigger.

      Reply
    5. September 23, 2022 at 7:14 am

      How to handle if class is final no default constructor.

      Reply

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.