Getting Started with Custom Deserialization in Jackson

1. Overview

This quick tutorial will illustrate how to use Jackson 2 to deserialize JSON using a custom Deserializer.

If you want to dig deeper and learn other cool things you can do with the Jackson 2 – head on over to the main Jackson tutorial.

2. Standard Deserialization

Let’s start by defining 2 entities and see how Jackson will deserialize a JSON representation to these entities without any customization:

public class User {
    public int id;
    public String name;
}
public class Item {
    public int id;
    public String itemName;
    public User owner;
}

Now, let’s define the JSON representation we want to deserialize:

{
    "id": 1,
    "itemName": "theItem",
    "owner": {
        "id": 2,
        "name": "theUser"
    }
}

And finally, let’s unmarshall this JSON to Java Entities:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

3. Custom Deserializer on ObjectMapper

In the previous example, the JSON representation matched the java entities perfectly – next, we will simplify the JSON:

{
    "id": 1,
    "itemName": "theItem",
    "createdBy": 2
}

When unmarshalling this to the exact same entities – by default, this will of course fail:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: 
Unrecognized field "createdBy" (class com.maixuanviet.jackson.dtos.Item), 
not marked as ignorable (3 known properties: "id", "owner", "itemName"])
 at [Source: java.io.StringReader@53c7a917; line: 1, column: 43] 
 (through reference chain: com.maixuanviet.jackson.dtos.Item["createdBy"])

We’ll solve this by doing our own deserialization with a custom Deserializer:

public class ItemDeserializer extends StdDeserializer<Item> { 

    public ItemDeserializer() { 
        this(null); 
    } 

    public ItemDeserializer(Class<?> vc) { 
        super(vc); 
    }

    @Override
    public Item deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        int id = (Integer) ((IntNode) node.get("id")).numberValue();
        String itemName = node.get("itemName").asText();
        int userId = (Integer) ((IntNode) node.get("createdBy")).numberValue();

        return new Item(id, itemName, new User(userId, null));
    }
}

As you can see, the deserializer is working with the standard Jackson representation of JSON – the JsonNode. Once the input JSON is represented as a JsonNode, we can now extract the relevant information from it and construct our own Item entity.

Simply put, we need to register this custom deserializer and simply deserialize the JSON normally:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Item.class, new ItemDeserializer());
mapper.registerModule(module);

Item readValue = mapper.readValue(json, Item.class);

4. Custom Deserializer on the Class

Alternatively, we can also register the deserializer directly on the class:

@JsonDeserialize(using = ItemDeserializer.class)
public class Item {
    ...
}

With the deserializer defined at the class level, there is no need to register it on the ObjectMapper – a default mapper will work fine:

Item itemWithOwner = new ObjectMapper().readValue(json, Item.class);

This type of per-class configuration is very useful in situations in which we may not have direct access to the raw ObjectMapper to configure.

5. Conclusion

This article shows how to leverage Jackson 2 to read non-standard JSON input – and how to map that input to any java entity graph with full control over the mapping.

The implementation of all these examples and code snippets can be found in over on GitHub – it’s a Maven-based project, so it should be easy to import and run as it is.

Related posts:

Spring Boot - Creating Docker Image
How to Set TLS Version in Apache HttpClient
Java Program to Generate a Sequence of N Characters for a Given Specific Case
4 tính chất của lập trình hướng đối tượng trong Java
Java Program to Implement Sorted Doubly Linked List
Daemon Threads in Java
Lập trình đa luồng với CompletableFuture trong Java 8
Introduction to Apache Commons Text
Custom Thread Pools In Java 8 Parallel Streams
Java Program to Perform Finite State Automaton based Search
Java Program to Implement Sorted Circularly Singly Linked List
Câu lệnh điều khiển vòng lặp trong Java (break, continue)
Java Program to Implement Fisher-Yates Algorithm for Array Shuffling
Guide to Dynamic Tests in Junit 5
Java Program to Implement Merge Sort on n Numbers Without tail-recursion
Converting Between Byte Arrays and Hexadecimal Strings in Java
Java Program to Implement an Algorithm to Find the Global min Cut in a Graph
How to Manually Authenticate User with Spring Security
Java Program to Implement Quick sort
Java Program to Implement HashMap API
Java Program to Implement Branch and Bound Method to Perform a Combinatorial Search
Java Program to Implement Uniform-Cost Search
Tìm hiểu về xác thực và phân quyền trong ứng dụng
A Guide to Concurrent Queues in Java
Spring Data MongoDB – Indexes, Annotations and Converters
Checked and Unchecked Exceptions in Java
REST Web service: Basic Authentication trong Jersey 2.x
Java Program to Implement the Monoalphabetic Cypher
Java 8 Stream findFirst() vs. findAny()
Format ZonedDateTime to String
Injecting Prototype Beans into a Singleton Instance in Spring
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...