Java Jackson @JsonBackReference Example

1. Introduction

When dealing with bi-directional relationships between objects, serialization can lead to infinite loops, causing a StackOverflowError. Jackson provides a way to manage this through the use of @JsonManagedReference and @JsonBackReference annotations. In this guide, we'll focus on the @JsonBackReference.

2. Example Steps

1. Create two classes: Author and Book. The Author has a list of books they've written, and each Book has a reference back to its author.

2. Annotate the 'author' field in the Book class with @JsonBackReference to indicate that it's the backward part of the relationship and should be ignored during serialization.

3. Serialize a sample Author object with associated Book objects to JSON.

4. Print the serialized JSON string.

3. Java Jackson @JsonBackReference Example

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonBackReference;
import java.util.List;

public class JsonBackReferenceExample {

    public static class Author {
        public int id;
        public String name;
        public List<Book> books;

        public Author(int id, String name, List<Book> books) {
            this.id = id;
            this.name = name;
            this.books = books;
        }
    }

    public static class Book {
        public int bookId;
        public String title;
        // Annotating the backward part of the relationship
        @JsonBackReference
        public Author author;

        public Book(int bookId, String title, Author author) {
            this.bookId = bookId;
            this.title = title;
            this.author = author;
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        Author author = new Author(1, "Jane", List.of(new Book(101, "Mystery Tales", null)));
        author.books.get(0).author = author;

        ObjectMapper mapper = new ObjectMapper();
        String result = mapper.writeValueAsString(author);

        System.out.println(result);
    }
}

Output:

{"id":1,"name":"Jane","books":[{"bookId":101,"title":"Mystery Tales"}]}

4. Step By Step Explanation

In object relationships where there's a bidirectional link, serializing one object can inadvertently lead to the serialization of its counterpart, which will then try to serialize the original object again, causing an endless loop.

In our sample, an Author has several Book entities, and each Book has a reference back to its Author. If we serialize without any special handling, the Author object would try to serialize its books, and each book would then attempt to serialize its author, leading to a never-ending cycle.

By using @JsonBackReference on the 'author' field in the Book class, we tell Jackson to omit this back-reference during serialization. This way, when a Book object is serialized, it doesn't try to serialize its author, thus breaking the potential loop.

The result is a clean JSON representation of the Author and their Book entities without unnecessary recursive back-references.


Comments