Java Language Custom JSON Deserialization with Jackson


Example

We consume rest API as a JSON format and then unmarshal it to a POJO. Jackson’s org.codehaus.jackson.map.ObjectMapper “just works” out of the box and we really don’t do anything in most cases. But sometimes we need custom deserializer to fulfill our custom needs and this tutorial will guide you through the process of creating your own custom deserializer.

Let’s say we have following entities.

public class User {
    private Long id;
    private String name;
    private String email;

    //getter setter are omitted for clarity 
}

And

public class Program {
    private Long id;
    private String name;
    private User createdBy;
    private String contents;

    //getter setter are omitted for clarity
}

Let’s serialize/marshal an object first.

User user = new User();
user.setId(1L);
user.setEmail("example@example.com");
user.setName("Bazlur Rahman");

Program program = new Program();
program.setId(1L);
program.setName("Program @# 1");
program.setCreatedBy(user);
program.setContents("Some contents");

ObjectMapper objectMapper = new ObjectMapper();

final String json = objectMapper.writeValueAsString(program); System.out.println(json);

The above code will produce following JSON-

{
    "id": 1,
    "name": "Program @# 1",
    "createdBy": {
        "id": 1,
        "name": "Bazlur Rahman",
        "email": "example@example.com"
    },
    "contents": "Some contents"
}

Now can do the opposite very easily. If we have this JSON, we can unmarshal to a program object using ObjectMapper as following –

Now let’s say, this is not the real case, we are going to have a different JSON from an API which doesn’t match with our Program class.

{
"id": 1,
"name": "Program @# 1",
"ownerId": 1
"contents": "Some contents"
}

Look at the JSON string, you can see, it has a different field that is owenerId.

Now if you want to serialize this JSON as we did earlier, you will have exceptions.

There are two ways to avoid exceptions and have this serialized –

Ignore the unknown fields

Ignore the onwerId. Add the following annotation in the Program class

@JsonIgnoreProperties(ignoreUnknown = true)
public class Program {}

Write custom deserializer

But there are cases when you actually need this owerId field. Let's say you want to relate it as an id of the User class.

In such case, you need to write a custom deserializer-

As you can see, first you have to access the JsonNode from the JonsParser. And then you can easily extract information from a JsonNode using the get() method. and you have to make sure about the field name. It should be the exact name, spelling mistake will cause exceptions.

And finally, you have to register your ProgramDeserializer to the ObjectMapper.

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Program.class, new ProgramDeserializer());
 
mapper.registerModule(module);
 
String newJsonString = "{\"id\":1,\"name\":\"Program @# 1\",\"ownerId\":1,\"contents\":\"Some contents\"}";
final Program program2 = mapper.readValue(newJsonString, Program.class);

Alternatively, you can use annotation to register the deserializer directly –

@JsonDeserialize(using = ProgramDeserializer.class)
public class Program {
}