Java
JSON
Jackson Library
Programming
Data Conversion

Converting Java objects to JSON with Jackson

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Jackson is the default JSON library in a large part of the Java ecosystem because it handles ordinary Java objects with very little ceremony. In the simplest case, you create an ObjectMapper, call writeValueAsString, and get JSON back.

The more interesting part is controlling output shape, dates, null handling, and nested objects without turning serialization into custom boilerplate. That is where a good Jackson setup matters.

Start With ObjectMapper

The central class is ObjectMapper. It knows how to inspect fields or getters, serialize collections, and write JSON to strings, streams, or files.

Here is a complete example:

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2
3class User {
4    private final long id;
5    private final String name;
6
7    public User(long id, String name) {
8        this.id = id;
9        this.name = name;
10    }
11
12    public long getId() {
13        return id;
14    }
15
16    public String getName() {
17        return name;
18    }
19}
20
21public class Main {
22    public static void main(String[] args) throws Exception {
23        ObjectMapper mapper = new ObjectMapper();
24        User user = new User(1L, "Ava");
25
26        String json = mapper.writeValueAsString(user);
27        System.out.println(json);
28    }
29}

Output:

json
{"id":1,"name":"Ava"}

Jackson can produce this because the class exposes readable properties through getters. Public fields also work, but normal getter-based domain objects are usually cleaner.

Serialize Collections and Nested Types

Jackson handles nested objects and lists naturally, which is why it fits REST APIs so well.

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2import java.util.List;
3
4class Address {
5    private final String city;
6    private final String country;
7
8    public Address(String city, String country) {
9        this.city = city;
10        this.country = country;
11    }
12
13    public String getCity() {
14        return city;
15    }
16
17    public String getCountry() {
18        return country;
19    }
20}
21
22class User {
23    private final String name;
24    private final Address address;
25
26    public User(String name, Address address) {
27        this.name = name;
28        this.address = address;
29    }
30
31    public String getName() {
32        return name;
33    }
34
35    public Address getAddress() {
36        return address;
37    }
38}
39
40public class Main {
41    public static void main(String[] args) throws Exception {
42        ObjectMapper mapper = new ObjectMapper();
43
44        List<User> users = List.of(
45            new User("Ava", new Address("Toronto", "Canada")),
46            new User("Ben", new Address("Berlin", "Germany"))
47        );
48
49        System.out.println(mapper.writeValueAsString(users));
50    }
51}

This gives a JSON array with nested objects, without any manual string assembly.

Control Names and Null Handling

Real APIs often need field names that differ from Java names, or they want to skip null values. Jackson annotations cover both cases cleanly.

java
1import com.fasterxml.jackson.annotation.JsonInclude;
2import com.fasterxml.jackson.annotation.JsonProperty;
3
4@JsonInclude(JsonInclude.Include.NON_NULL)
5class UserDto {
6    @JsonProperty("full_name")
7    private final String name;
8
9    private final Integer age;
10
11    public UserDto(String name, Integer age) {
12        this.name = name;
13        this.age = age;
14    }
15
16    public String getName() {
17        return name;
18    }
19
20    public Integer getAge() {
21        return age;
22    }
23}

With that definition, Jackson emits full_name and omits age when it is null. This is usually better than post-processing JSON text after serialization.

Pretty Printing and Reusable Configuration

For debugging, fixtures, and local tools, pretty printing makes output easier to read:

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2import com.fasterxml.jackson.databind.SerializationFeature;
3
4ObjectMapper mapper = new ObjectMapper()
5    .enable(SerializationFeature.INDENT_OUTPUT);

In production code, do not create a new mapper in every method. Build one configured mapper and reuse it. That keeps behavior consistent across the application, especially for:

  • Java time serialization
  • naming strategy
  • null inclusion rules
  • custom modules
  • pretty-print behavior in specific environments

Frameworks such as Spring Boot usually manage this for you, but the principle is the same even in plain Java.

Writing to Files or Streams

You do not always need an intermediate String. Jackson can write directly to a destination:

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2import java.nio.file.Path;
3
4ObjectMapper mapper = new ObjectMapper();
5User user = new User(1L, "Ava");
6
7mapper.writeValue(Path.of("user.json").toFile(), user);

This is often the right choice for exports, test fixtures, or CLI tools because it avoids one more conversion step.

Common Pitfalls

One common mistake is thinking toString() affects Jackson output. It does not. Jackson serializes the object's properties, not its string representation.

Another problem is scattering many local ObjectMapper instances through the codebase. That produces subtle differences in JSON shape, date formatting, and null handling that are hard to track down later.

Developers also run into visibility issues. If a class has no visible fields, no getters, or uses constructors in a way Jackson cannot infer, the output may be empty or fail unexpectedly. When that happens, inspect the class design first instead of blaming JSON generation broadly.

Finally, avoid manual string concatenation to build JSON. It is brittle, escapes poorly, and becomes a maintenance problem as soon as the object shape grows.

Summary

  • Jackson uses ObjectMapper to convert Java objects into JSON.
  • 'writeValueAsString is the simplest way to produce a JSON string.'
  • Collections and nested objects serialize naturally when the object model is clear.
  • Use annotations such as @JsonProperty and @JsonInclude to control output shape.
  • Reuse a configured ObjectMapper instead of creating ad hoc mappers throughout the application.

Course illustration
Course illustration

All Rights Reserved.