반응형

@JsonManagedReference와 @JsonBackReference 어노테이션 사용

  • Jackson 2.0 버전 이전에 순환 참조를 해결하기 위해 사용했던 어노테이션입니다.
  • @JsonManagedReference
    • 양방향 관계에서 정방향 참조할 변수에 어노테이션을 추가하면 직렬화에 포함된다.
  • @JsonBackReference
    • 양방향 관계에서 역방향 참조로 어노테이션을 추가하면 직렬화에서 제외된다.

Customer 객체에서 Order 객체에 @JsonManagedReference를 추가하고 Order에서는 Customer 객체에 @JsonBackReference 어노테이션을 추가하여 직렬화에서 Customer 객체를 제외 시켰습니다.

@Setter
@Getter
@ToString
public class Customer {
    private int id;
    private String name;
    @JsonManagedReference //serialized될 때 포함됨
    private Order order;
}

@Setter
@Getter
@ToString(exclude = "customer”) //toString() 실행시에도 무한 재귀가 발생하여 제외시킨다
public class Order {
    private int orderId;
    private List<Integer> itemIds;
    @JsonBackReference //serialization에서 제외된다
    private Customer customer;
}

@Test
public void infinite_recursion_해결책_JsonManagedReference_JsonBackReference() throws JsonProcessingException {
    Order order = new Order();
    order.setOrderId(1);
    order.setItemIds(List.of(10, 30));

    Customer customer = new Customer();
    customer.setId(2);
    customer.setName("Frank");
    customer.setOrder(order);
    order.setCustomer(customer);

    log.info("customer(toString) : {}", customer);
    log.info("customer(serialized json) : {}", objectMapper.writeValueAsString(customer));
    log.info("order(serialized json) : {}", objectMapper.writeValueAsString(order)); //customer정보는 제외된다
}

실행 화면

@JsonBackReference 어노테이션 선언으로 Order 객체에서 Customer 객체에 대한 정보는 빠지게 됩니다.

@JsonIdentityInfo - 추천 방식

  • Jackson 2.0 이후부터 새롭게 추가된 어노테이션입니다. @JsonIdentityInfo 어노테이션을 추가해서 직렬화에 포함 시킬 속성 값을 'property' 속성에 지정합니다.
  • @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
    • generator = ObjectIdGenerators.PropertyGenerator.class 클래스는 순환 참조시 사용할 Id를 생성하는데 사용되는 클래스이다.
  • @JsonIdentityInfo(property="id")
    • property 속성은 해당 클래스의 속성 이름을 지정한다.
    • 예제에서는 id는 Customer#id를 가리키고 직렬화/역직렬화 할 때 Order#customer의 역참조로 사용된다.

@JsonIgnore

제일 간단하게 해결할 수 있는 방법은 직렬화 할 때 순환 참조 되는 속성에 @JsonIgnore 어노테이션을 추가하여 직렬화에서 제외시키는 방법입니다.

@JsonIgnore
private Customer customer;

해당 customer 필드는 직렬화에서 제외되어 json 형태에 표시되지 않습니다.

반응형

+ Recent posts