Java Jackson @JsonIdentityReference Example

1. Introduction

Handling bidirectional relationships in Java can be tricky when converting objects to JSON, as they can lead to infinite loops during serialization. Jackson provides a solution with the @JsonIdentityInfo and @JsonIdentityReference annotations. In this guide, we will focus on the @JsonIdentityReference annotation, which allows representing a referenced entity with its ID rather than the full serialization.

2. Example Steps

1. Add the necessary Jackson library dependencies to your project.

2. Create Java classes representing a bidirectional relationship.

3. Annotate one side of the relationship with @JsonIdentityInfo and @JsonIdentityReference.

4. Use Jackson's ObjectMapper class to serialize the Java object.

5. Display the results.

3. Java Jackson @JsonIdentityReference Example

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonIdentityReferenceExample {

    public static void main(String[] args) {
        // Initialize ObjectMapper instance.
        ObjectMapper objectMapper = new ObjectMapper();

        // Create objects with a bidirectional relationship.
        Book book = new Book("A Tale of Two Cities");
        Author author = new Author("Charles Dickens");
        book.setAuthor(author);
        author.setBook(book);

        try {
            // Serialize the Java object to JSON string.
            String jsonString = objectMapper.writeValueAsString(book);
            System.out.println("Serialized JSON: " + jsonString);

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    static class Author {
        private String name;
        @JsonIdentityReference(alwaysAsId = true)
        private Book book;

        // Constructor, getters, setters, and other methods...
    }

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "title")
    static class Book {
        private String title;
        private Author author;

        // Constructor, getters, setters, and other methods...
    }
}

Output:

Serialized JSON: {"title":"A Tale of Two Cities","author":{"name":"Charles Dickens","book":"A Tale of Two Cities"}}

4. Step By Step Explanation

1. We have two classes, Book and Author, representing a bidirectional relationship.

2. The @JsonIdentityInfo annotation on the Book class instructs Jackson to use the title property of the book as its identifier.

3. In the Author class, the @JsonIdentityReference annotation with the attribute alwaysAsId = true tells Jackson to serialize the book reference using its ID (in this case, the title) rather than the full object.

4. After setting up the bidirectional relationship between a book and its author, we serialize the book object. In the JSON output, the book property in the Author class is represented by its title, as instructed by our annotations.