Spring/스프링 기본

@Json~~~ 관련 annotation 정리

공대키메라 2022. 2. 3. 11:13

우리가 클래스를 하나 만들었다고 가정하자. 

 

...

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Users {
    @Id
    @GeneratedValue
    private Integer id;

    @Size(min = 2, message="Name은 2글자 이상 입력해 주세요.")
    private String name;
    @Past
    private Date joinDate;

    private String password;

    private String ssn;

}

 

위의 정보를 바탕으로 사용자 정보를 조회하고 싶은데 조회할 때 마다 아니... password가 같이 넘어오게 된다. 

 

이러한 경우 조회시 필드에서 제외하고 싶은 성분을 @JsonIgnore 어노테이션으로 제거가 가능하다!

 

오늘은 이와 관련된 기능들에 대해서 아~주 간단하게 정리하려한다. 

 

1. @JsonIgnore

무시하길 원하는 속성을 표시할 때 사용. 속성 위에 선언하면 끝

 

...
public class Users {

  ...

    @JsonIgnore
    private String password;
    
    @JsonIgnore
    private String ssn;

}

 

2. @JsonIgnoreProperties

필드 레벨에서 @JsonIgnore를 선언하지 않고 클래스 레벨에서 @JsonIgnoreProperties를 사용해도 제외할 성분을 선택할 수 있다. 

 

...
@JsonIgnoreProperteis({"password", "ssn"})
public class Users {

  ...

    //@JsonIgnore
    private String password;
    
    //@JsonIgnore
    private String ssn;

}

 

3. @JsonFilter

@JsonFilter는 메서드내에서 원하는 필드를 다룰 수 있다. 

 

우선 클래스 레벨에 @JsonFilter 어노테이션 뒤에 원하는 이름을 입력한다. 

 

 

package com.example.demo.user;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@JsonFilter("UserInfoFilter")  // <=============== 요기여~
public class Users {
    @Id
    @GeneratedValue
    private Integer id;

    @Size(min = 2, message="Name은 2글자 이상 입력해 주세요.")
    private String name;
    @Past
    private Date joinDate;

    private String password;

    private String ssn;

}

 

그리고 SimpleBeanPropertieFilter를 선언해서 필터에 더해서 MappingJacksonValue로 반환해주면 끝~!

 

@GetMapping("/users")
public MappingJacksonValue retrieveAllUsers(){
    List<Users> users = service.findAll();
    SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
            .filterOutAllExcept("id", "name", "joinDate","password");

    FilterProvider filters = new SimpleFilterProvider().addFilter("UserInfoFilter", filter);

    MappingJacksonValue mapping = new MappingJacksonValue(users);
    mapping.setFilters(filters);
    return mapping;
}

 

코드로 구현하니 손이 더 가는것 같지만 동적으로 filter기능을 이용해 데이터를 선별하고 싶다면 이런 방식을 사용해야 할 듯 하다. 

 

- 관련 문제 해결 경험

JPA에서 필자가 생각하기에 이것만 알면 다 아네~ 하는 개념이 몇가지 있다. 

영속성 관리, 연관관계 설정(일대다, 다대일), n+1문제가 핵심이라고 생각한다. 

이중에서 연관관계가 설정된 친구를 조회할 때 문제가 발생하는데...

서로 양방향에서 바라보고 있는 테이블을 조회하게 되면 무한 루프에 빠지게 되는 것이다!

이런 경우에는 위에서 설명했듯이 무한루프에 빠진 속성을 데이터 조회시 무시해야 한다!

 

 

2 - 다른 이름으로 매핑

 

전에 Users클래스를 생성했는데 이와 같은 이름으로 매핑되지 않고 다른 이름으로 데이터가 넘어오면 어떻게 할까?

 

그럴때는 @JsonProperty, @JsonNaming을 사용하면 된다. 

 

name => user_name

password => user_password

 

...

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@JsonNaming(PropertiyNamingStrategy.SnakeCaseStrategy.class)
public class Users {
    @Id
    @GeneratedValue
    private Integer id;

    @Size(min = 2, message="Name은 2글자 이상 입력해 주세요.")
    @JsonProperty("user_name") <======== 추가
    private String name;
    @Past
    private Date joinDate;
    @JsonProperty("user_password")  <======== 추가
    private String password;

    private String ssn;

}

 

근데 이름이 너무 다르다면 JsonProperty만 사용해야겠지만 _로 비슷한 형식으로 이어진 경우에는 JsonNaming 어노테이션을 사용할 수 있다.

 

내부적으로 보면 대문자가 나오는 자리에 _와 소문자로 바꿔 넣어주는 간단한 구조를 가지고 있다

 

 

'Spring > 스프링 기본' 카테고리의 다른 글

Glory of Rest 란 뭘까? + HATEOS 적용기  (0) 2022.02.16
Spring Web Socket 적용하기  (2) 2022.02.04
Spring VS Spring boot  (3) 2022.02.03
Bean이란?  (2) 2022.01.28
MVC 어노테이션 정리  (0) 2022.01.19