Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

Tầm quan trọng của @JsonIdentityInfo trong Jackson (Java)

Annotation @JsonIdentityInfo giải quyết vấn đề **circular reference** (tham chiếu vòng) khi serialize object có quan hệ parent-child (bidirectional). Nó dùng **Object Identity** để tham chiếu object đã serialize thay vì lồng lặp vô tận.

Cú pháp

@Target({ANNOTATION_TYPE, TYPE, FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface JsonIdentityInfo {
    Class<? extends ObjectIdGenerator> generator() default ObjectIdGenerators.IntSequenceGenerator.class;
    String property() default "";
    // ... các thuộc tính khác: scope, resolver...
}

Ví dụ: Quan hệ User - Address (Bidirectional)

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;

public class JsonIdentityInfoTest {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        
        User user = new User(115, "Raja", "Ramesh");
        Address address = new Address(125, "Madhapur", "Hyderabad", user);
        user.addAddress(address);
        
        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(address);
        System.out.println(json);
    }
}

@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class, 
    property = "userId"
)
class User {
    private int userId;
    private String firstName, lastName;
    private List<Address> addresses = new ArrayList<>();
    
    public User(int userId, String firstName, String lastName) {
        this.userId = userId; this.firstName = firstName; this.lastName = lastName;
    }
    // getters...
    public void addAddress(Address a) { addresses.add(a); }
}

@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class, 
    property = "userId"
)
class Address {
    private int userId; // Property dùng làm ID
    private String city, street;
    private User user;  // Back-reference
    
    public Address(int userId, String street, String city, User user) {
        this.userId = userId; this.street = street; this.city = city; this.user = user;
    }
    // getters...
}

Output

{
  "userId" : 125,
  "city" : "Hyderabad",
  "street" : "Madhapur",
  "user" : {
    "userId" : 115,
    "firstName" : "Raja",
    "lastName" : "Ramesh"
  }
}

Không có @JsonIdentityInfo: Serialize address → user → addresses → address → ... → StackOverflowError.

Các Generator phổ biến

  • PropertyGenerator: Dùng property của object làm ID (như ví dụ userId).
  • IntSequenceGenerator: Tự gán ID số nguyên tăng dần (mặc định).
  • UUIDGenerator: Dùng UUID.
  • Custom Generator: Implement ObjectIdGenerator.

Lưu ý

  • Cả hai phía quan hệ (parent & child) đều cần @JsonIdentityInfo với generator/property tương thích.
  • Property dùng làm ID phải **unique** trong scope serialization.
  • Deserialize: Jackson tự resolve reference dựa trên ID.
  • Alternative: @JsonManagedReference + @JsonBackReference (xem bài tiếp theo).