Java Jackson @JsonSubTypes

1. Overview

Jackson, a pivotal Java library, excels in transforming Java objects into JSON and vice versa. When working with object hierarchies and polymorphism in Java, deserializing the JSON back to the correct subtype becomes challenging. Jackson’s @JsonSubTypes annotation aids in addressing this very issue.

@JsonSubTypes Annotation Overview

The @JsonSubTypes annotation is used in tandem with the @JsonTypeInfo annotation to specify the subtypes of a given parent type. This ensures that Jackson can deserialize JSON data into the appropriate subtype based on the included metadata.

2. Development Steps

1. Start a new Maven project.

2. Add the necessary Jackson dependencies.

3. Create a User superclass, specify subtypes using @JsonSubTypes, and apply the @JsonTypeInfo annotation.

4. Implement a separate class for the serialization process.

5. Craft a main class to illustrate the serialization and deserialization.

3. Create a Maven Project

There are different ways to create a simple Maven project:

Create a Simple Maven Project using the Command Line Interface

Create a Simple Maven Project using  Eclipse IDE

Create a Simple Maven Project using  IntelliJ IDEA

4. Maven Dependencies

Open the pom.xml file, and add the following Jackson data binding dependency:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

5. Code Program

Using the User Management System for illustration:
// User.java
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "userType")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Admin.class, name = "admin"),
        @JsonSubTypes.Type(value = Guest.class, name = "guest")
})
public abstract class User {
    private String username;
    // Constructors, getters, setters...
}
class Admin extends User {
    private String adminRole;
    // Constructors, getters, setters...
}
class Guest extends User {
    private boolean hasTempAccess;
    // Constructors, getters, setters...
}
// JsonSerializer.java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonSerializer {
    public static String serializeToJson(User user) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(user);
    }
    public static User deserializeFromJson(String json) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json, User.class);
    }
}
// MainClass.java
public class MainClass {
    public static void main(String[] args) {
        User guest = new Guest();
        guest.setUsername("JohnDoe");
        ((Guest) guest).setHasTempAccess(true);
        try {
            String json = JsonSerializer.serializeToJson(guest);
            System.out.println("Serialized JSON: " + json);
            User deserializedUser = JsonSerializer.deserializeFromJson(json);
            System.out.println("Deserialized User: " + deserializedUser.getUsername());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

Output:

Serialized JSON: {"userType":"guest","username":"JohnDoe","hasTempAccess":true}
Deserialized User: JohnDoe

Code Explanation:

The User class, being abstract, has two subtypes: Admin and Guest

Using the @JsonSubTypes annotation, we specify these subtypes. 

The @JsonTypeInfo annotation indicates how subtype information should be included during serialization. 

The JsonSerializer class showcases both serialization and deserialization using Jackson's ObjectMapper

The MainClass demonstrates the process by creating a Guest instance, serializing it to JSON, and then deserializing it back to a User object.

6. Conclusion

The @JsonSubTypes annotation in Jackson enables seamless serialization and deserialization of polymorphic Java types. By clearly specifying subtypes, developers can ensure type safety and consistency when converting between JSON and Java objects in applications.

Comments