JSON is not new to developers, as most of today’s web services, mobile applications, and even the Internet of Things use JSON as a data exchange format. Learning the tools for manipulating the JSON format is essential for developers. This article will describe how to use Jackson, an open source tool library, to perform common operations on JSON.

json

JSON Introduction

What is JSON?JSON stands for “JavaScript Object Notation”, JSON is a text-based format that can be understood as a structured data that can contain key-value mapping, nested objects and arrays of information.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "array": [
    1,
    2,
    3
  ],
  "boolean": true,
  "color": "gold",
  "null": null,
  "number": 123,
  "object": {
    "a": "b",
    "c": "d"
  },
  "string": "www.wdbyte.com"
}

Jackson Introduction

Jackson and FastJson as well, is a Java language written for JSON processing open source tool library , Jackson is very widely used , Spring Framework default use Jackson for JSON processing .

Jackson has three core packages, namely Streaming, Databid, Annotations, through which you can easily operate on JSON.

  • Streaming in the jackson-core module. Defines a number of APIs related to stream processing and specific JSON implementations.
  • Annotations in the jackson-annotations module, contains annotations in Jackson.
  • Databind in the jackson-databind module, implements databinding on top of the Streaming package, relying on Streaming and Annotations packages.

Thanks to Jackson’s highly extensible design, there are many common text formats and tools that have adaptations for Jackson, such as CSV, XML, YAML, etc.

Jackson Maven dependencies

When using Jackson, in most cases we just need to add the jackson-databind dependency to use the Jackson functionality, which depends on the following two packages.

Jackson Maven dependencies

  • com.fasterxml.jackson.core:jackson-annotations
  • com.fasterxml.jackson.core:jackson-core
1
2
3
4
5
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

To facilitate the code demonstration that follows in this article, we import both Junit for unit testing and Lombok to reduce Get/Set code writing.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
</dependency>

ObjectMapper

ObjectMapper is one of the most commonly used classes in the Jackson library for fast conversion between Java objects and JSON strings. If you have used FastJson, then ObjectMapper in Jackson is like the JSON class in FastJson.

There are some common methods in this class.

  • readValue() method can perform JSON deserialization operations, such as converting strings, file streams, byte streams, byte arrays, and other common content into Java objects.
  • writeValue() method can perform JSON serialization operations, which can convert Java objects into JSON strings.

Most of the time, ObjectMapper works by mapping the Java bean objects through their Get/Set methods, so it is important to write the Get/Set methods of Java objects correctly, but ObjectMapper also provides a lot of configurations. For example, you can customize the conversion process between Java objects and JSON strings through configuration or annotations. These are described in the following sections.

Jackson JSON Basic Operations

Jackson is a JSON tool library in Java, and handling JSON strings and Java objects is its most basic and common function. Here are some examples to demonstrate the usage.

Jackson JSON Serialization

Write a Person class that defines three properties, name, age, and skill.

1
2
3
4
5
6
7
8
9
/**
 * @author https://www.wdbyte.com
 */
@Data
public class Person {
    private String name;
    private Integer age;
    private List<String> skillList;
}

Converts a Java object to a JSON string.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Arrays;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class PersonTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void pojoToJsonString() throws JsonProcessingException {
        Person person = new Person();
        person.setName("aLng");
        person.setAge(27);
        person.setSkillList(Arrays.asList("java", "c++"));

        String json = objectMapper.writeValueAsString(person);
        System.out.println(json);
        String expectedJson = "{\"name\":\"aLng\",\"age\":27,\"skillList\":[\"java\",\"c++\"]}";
        Assertions.assertEquals(json, expectedJson);
    }
}

The output JSON string is as follows.

1
{"name":"aLng","age":27,"skillList":["java","c++"]}

Jackson can even write the serialized JSON string directly to a file or read it as a byte array.

1
2
3
4
5
mapper.writeValue(new File("result.json"), myResultObject);
// or
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
// or
String jsonString = mapper.writeValueAsString(myResultObject);

Jackson JSON deserialization

The code is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.wdbyte.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class PersonTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void jsonStringToPojo() throws JsonProcessingException {
        String expectedJson = "{\"name\":\"aLang\",\"age\":27,\"skillList\":[\"java\",\"c++\"]}";
        Person person = objectMapper.readValue(expectedJson, Person.class);
        System.out.println(person);
        Assertions.assertEquals(person.getName(), "aLang");
        Assertions.assertEquals(person.getSkillList().toString(), "[java, c++]");
    }
}

The output is as follows.

1
Person(name=aLang, age=27, skillList=[java, c++])

The above example shows how to use Jackson to deserialize a JSON string into a Java object, but in fact it is just as easy for Jackson to deserialize a JSON string in a file, or in byte form.

First, prepare a JSON file Person.json with the following contents.

1
2
3
4
5
6
7
8
{
  "name": "aLang",
  "age": 27,
  "skillList": [
    "java",
    "c++"
  ]
}

Read this file and deserialize it to a java object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ObjectMapper objectMapper = new ObjectMapper();

@Test
void testJsonFilePojo() throws IOException {
    File file = new File("src/Person.json");
    Person person = objectMapper.readValue(file, Person.class);
    // or
    // person = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class);
    System.out.println(person);
    Assertions.assertEquals(person.getName(), "aLang");
    Assertions.assertEquals(person.getSkillList().toString(), "[java, c++]");
}

The output is as follows.

1
Person(name=aLang, age=27, skillList=[java, c++])

JSON to List

The above demonstrates that JSON strings are all single objects, if JSON is a list of objects then how do you handle it using Jackson?

There is already a file PersonList.json with the following contents.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[
  {
    "name": "aLang",
    "age": 27,
    "skillList": [
      "java",
      "c++"
    ]
  },
  {
    "name": "darcy",
    "age": 26,
    "skillList": [
      "go",
      "rust"
    ]
  }
]

Read it and convert it to List<Person>.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
ObjectMapper objectMapper = new ObjectMapper();

@Test
void fileToPojoList() throws IOException {
    File file = new File("src/EmployeeList.json");
    List<Person> personList = objectMapper.readValue(file, new TypeReference<List<Person>>() {});
    for (Person person : personList) {
        System.out.println(person);
    }
    Assertions.assertEquals(personList.size(), 2);
    Assertions.assertEquals(personList.get(0).getName(), "aLang");
    Assertions.assertEquals(personList.get(1).getName(), "darcy");
}

The output is as follows.

1
2
Person(name=aLang, age=27, skillList=[java, c++])
Person(name=darcy, age=26, skillList=[go, rust])

JSON to Map

JSON to Map is useful when we don’t have a Java object, here’s how to use Jackson to convert JSON text to Map objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ObjectMapper objectMapper = new ObjectMapper();

@Test
void jsonStringToMap() throws IOException {
    String expectedJson = "{\"name\":\"aLang\",\"age\":27,\"skillList\":[\"java\",\"c++\"]}";
    Map<String, Object> employeeMap = objectMapper.readValue(expectedJson, new TypeReference<Map>() {});
    System.out.println(employeeMap.getClass());
    for (Entry<String, Object> entry : employeeMap.entrySet()) {
        System.out.println(entry.getKey() + ":" + entry.getValue());
    }
    Assertions.assertEquals(employeeMap.get("name"), "aLang");
}

The output is as follows.

1
2
3
4
class java.util.LinkedHashMap
name:aLang
age:27
skillList:[java, c++]

Jackson ignores fields

If when doing a JSON to Java object conversion. If there are properties in JSON that do not exist in the Java class, then an exception is thrown: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.

Non-existent properties can be ignored by setting objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ObjectMapper objectMapper = new ObjectMapper();

@Test
void jsonStringToPojoIgnoreProperties() throws IOException {
    // UnrecognizedPropertyException
    String json = "{\"yyy\":\"xxx\",\"name\":\"aLang\",\"age\":27,\"skillList\":[\"java\",\"c++\"]}";
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    Person person = objectMapper.readValue(json, Person.class);
    System.out.printf(person.toString());
    Assertions.assertEquals(person.getName(), "aLang");
    Assertions.assertEquals(person.getSkillList().toString(), "[java, c++]");
}

The output is as follows.

1
Person(name=aLang, age=27, skillList=[java, c++])

Jackson Date Formatting

Before Java 8 we usually used the java.util.Date class to handle time, but when Java 8 was released a new time class was introduced java.time.LocalDateTime. The two are handled slightly differently in Jackson.

First create an Order class with two time type properties.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.wdbyte.jackson;

import java.time.LocalDateTime;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author https://www.wdbyte.com
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
  
    private Integer id;

    private Date createTime;

    private LocalDateTime updateTime;
}

Date type

Let’s create a new test case to test the JSON conversion of the two time types.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.wdbyte.jackson;

import java.time.LocalDateTime;
import java.util.Date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class OrderTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testPojoToJson0() throws JsonProcessingException {
        Order order = new Order(1, new Date(), null);
        String json = objectMapper.writeValueAsString(order);
        System.out.println(json);

        order = objectMapper.readValue(json, Order.class);
        System.out.println(order.toString());

        Assertions.assertEquals(order.getId(), 1);
    }

}

In this test code, we have only initialized the Date type property, and here is the output.

1
2
{"id":1,"createTime":1658320852395,"updateTime":null}
Order(id=1, createTime=Wed Jul 20 20:40:52 CST 2022, updateTime=null)

You can see that the JSON serialization and deserialization is done normally, but the time in the JSON is in a timestamp format, which may not be what we want.

LocalDateTime type

Why isn’t the value of the LocalDateTime type property set? Because by default JSON conversion of the LocalDateTime class throws an exception.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
/**
 * @author https://www.wdbyte.com
 */
class OrderTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testPojoToJson() throws JsonProcessingException {
        Order order = new Order(1, new Date(), LocalDateTime.now());
        String json = objectMapper.writeValueAsString(order);
        System.out.println(json);

        order = objectMapper.readValue(json, Order.class);
        System.out.println(order.toString());

        Assertions.assertEquals(order.getId(), 1);
    }
}

Running it will throw an exception.

1
2
3
4
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
            Java 8 date/time type `java.time.LocalDateTime` not supported by default: 
                add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" 
          to enable handling (through reference chain: com.wdbyte.jackson.Order["updateTime"])

Here we need to add the appropriate data binding support libraries.

Adding dependencies.

1
2
3
4
5
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.3</version>
</dependency>

Then the dependencies are registered with the findAndRegisterModules() method when the ObjectMapper is defined.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.time.LocalDateTime;
import java.util.Date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class OrderTest {

    ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();

    @Test
    void testPojoToJson() throws JsonProcessingException {
        Order order = new Order(1, new Date(), LocalDateTime.now());
        String json = objectMapper.writeValueAsString(order);
        System.out.println(json);

        order = objectMapper.readValue(json, Order.class);
        System.out.println(order.toString());

        Assertions.assertEquals(order.getId(), 1);
    }
}

Running it gives you the normal serialization and deserialization logs, though the time format after serialization remains strange.

1
2
{"id":1,"createTime":1658321191562,"updateTime":[2022,7,20,20,46,31,567000000]}
Order(id=1, createTime=Wed Jul 20 20:46:31 CST 2022, updateTime=2022-07-20T20:46:31.567)

Time formatting

Customize the time format by using the annotation @JsonFormat on the field.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import java.time.LocalDateTime;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {

    private Integer id;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
    private LocalDateTime updateTime;
}

Run the above column again to get the time-formatted JSON string.

1
2
{"id":1,"createTime":"2022-07-20 20:49:46","updateTime":"2022-07-20 20:49:46"}
Order(id=1, createTime=Wed Jul 20 20:49:46 CST 2022, updateTime=2022-07-20T20:49:46)

Jackson common annotations

@JsonIgnore

Use @JsonIgnore to ignore attributes in a Java object that will not participate in JSON serialization and deserialization.

Example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.wdbyte.jackson;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

/**
 * @author https://www.wdbyte.com
 */
@Data
public class Cat {

    private String name;

    @JsonIgnore
    private Integer age;
}

Write unit test classes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.wdbyte.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class CatTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testPojoToJson() throws JsonProcessingException {
        Cat cat = new Cat();
        cat.setName("Tom");
        cat.setAge(2);
        String json = objectMapper.writeValueAsString(cat);
        System.out.println(json);

        Assertions.assertEquals(json, "{\"name\":\"Tom\"}");

        cat = objectMapper.readValue(json, Cat.class);
        Assertions.assertEquals(cat.getName(), "Tom");
        Assertions.assertEquals(cat.getAge(), null);
    }

}

You can see that the value of the age property in the output is null.

@JsonGetter

Use @JsonGetter to customize property names when JSON serializing Java objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;

/**
 * @author https://www.wdbyte.com
 */
@Data
public class Cat {

    private String name;

    private Integer age;

    @JsonGetter(value = "catName")
    public String getName() {
        return name;
    }
}

Write unit test classes for testing.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class CatTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testPojoToJson2() throws JsonProcessingException {
        Cat cat = new Cat();
        cat.setName("Tom");
        cat.setAge(2);
        String json = objectMapper.writeValueAsString(cat);
        System.out.println(json);
        Assertions.assertEquals(json, "{\"age\":2,\"catName\":\"Tom\"}");
    }
}

The output is as follows. java object’s name property name has been serialized to catName.

1
{"age":2,"catName":"Tom"}

@JsonSetter

Use @JsonSetter to set the mapping of keys in JSON to Java properties when deserializing JSON.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.wdbyte.jackson;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import lombok.Data;

/**
 * @author https://www.wdbyte.com
 * @date 2022/07/17
 */
@Data
public class Cat {
    @JsonSetter(value = "catName")
    private String name;

    private Integer age;

    @JsonGetter(value = "catName")
    public String getName() {
        return name;
    }
}

Write unit test classes for testing.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class CatTest {

    ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testPojoToJson2() throws JsonProcessingException {
        String json = "{\"age\":2,\"catName\":\"Tom\"}";
        Cat cat = objectMapper.readValue(json, Cat.class);
        System.out.println(cat.toString());
        Assertions.assertEquals(cat.getName(), "Tom");
    }
}

The output is as follows.

1
Cat(name=Tom, age=2)

@JsonAnySetter

The @JsonAnySetter allows you to handle all the properties that do not exist in the Java object when deserializing JSON. The following code demonstrates storing non-existent properties into a Map collection.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author https://www.wdbyte.com
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String name;
    private Integer age;
    private Map<String, Object> diyMap = new HashMap<>();

    @JsonAnySetter
    public void otherField(String key, String value) {
        this.diyMap.put(key, value);
    }
}

Write unit test cases.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 * @author https://www.wdbyte.com
 */
class StudentTest {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testJsonToPojo() throws JsonProcessingException {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "aLang");
        map.put("age", 18);
        map.put("skill", "java");

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

        Student student = objectMapper.readValue(json, Student.class);
        System.out.println(student);

        Assertions.assertEquals(student.getDiyMap().get("skill"), "java");
    }

}

You can see from the output that the skill property in JSON is placed in the diyMap collection because it is not in the Java class Student.

1
2
{"skill":"java","name":"aLang","age":18}
Student(name=aLang, age=18, diyMap={skill=java})

@JsonAnyGetter

Use @JsonAnyGetter to make the Map collection of Java objects as the source of properties in JSON when serializing them. Here’s an example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

/**
 * @author https://www.wdbyte.com
 */
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    @Getter
    @Setter
    private String name;

    @Getter
    @Setter
    private Integer age;
  
    @JsonAnyGetter
    private Map<String, Object> initMap = new HashMap() {{
        put("a", 111);
        put("b", 222);
        put("c", 333);
    }};
}

The output is as follows.

1
{"name":"aLang","age":20,"a":111,"b":222,"c":333}

Jackson Summary

  • Jackson is one of the more popular JSON processing libraries in Java, and it is the default JSON tool for Spring.
  • Jackson has three main modules, Streaming API, Annotations and Data Binding.
  • The ObjectMapper class in Jackson is very powerful for JSON related processing and can be combined with annotations and configuration for custom conversion logic.
  • Jackson is very extensible, such as CSV, XML, YAML format processing have corresponding adaptations for Jackson and so on.

The code related to this article can be found here.

Reference https://www.wdbyte.com/tool/jackson.html