Spring Boot

JSON_ARRAYAGG & @JsonRawValue

99duuk 2024. 9. 24. 11:08

데이터베이스에서 테이블 조회할 때, 대부분 컬럼(AAA, BBB, CCC, DDD, EEE)은 값이 같은데, 딱 하나(JJJ)만 여러 값을 가지는 상황이 생겼음

AAA~EEE 값이 같아도 JJJ 값이 다르면 별도의 행으로 나옴

 

 

 

 

우선, SQL에서 JSON_ARRAYAGG 함수를 써서 여러 값 가진 컬럼을 JSON 배열로 바꿨음.

SELECT AAA, BBB, CCC, DDD, EEE, JSON_ARRAYAGG(DISTINCT JJJ) AS JJJ
FROM TABLE
...
GROUP BY AAA, BBB, CCC, DDD, EEE

이렇게 하니까 쿼리 결과는 원했던 대로  [10, 20, 30] 이런 식으로 잘 나왔음

 

 

 

 

 

 

다음으로, 이 데이터 담을 DTO를 만들었음. 
RestController 사용해서 응답할거라 어차피 json 파싱이 필요할텐데 굳이 dto에 넣을 때 json to string 파싱이 필요할까?

싶어서 그냥 그대로 스트링에 박아버림

 

public class MyDTO {
    private String AAA;
    private String BBB;
    private String CCC;
    private String DDD;
    private String EEE;
    private String JJJ;

    // getter랑 setter들
}

 

 

RestController 쓰니까 그대로 나오지 않을까? 했는데 

{
  "AAA": "A",
  "BBB": "B",
  "CCC": "C",
  "DDD": "D",
  "EEE": "E",
  "JJJ": "[\"10\", \"20\", \"30\"]"
}

JJJ 필드가 JSON 배열이 아니라 그냥 문자열로 처리돼서 이렇게 나옴

 

 

 

 

@JsonRawValue 어노테이션을 씀

import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.annotation.JsonProperty;

@Getter
@Setter
public class MyDTO {
    private String AAA;
    private String BBB;
    private String CCC;
    private String DDD;
    private String EEE;
    
    @JsonRawValue
    @JsonProperty("JJJ")
    private String JJJ;
}

 

 

 

이렇게 고치니까, 컨트롤러 응답이 요렇게 바뀜

{
  "AAA": "A",
  "BBB": "B",
  "CCC": "C",
  "DDD": "D",
  "EEE": "E",
  "JJJ": ["10", "20", "30"]
}

 

 

 

 

 

 

  • JSON_ARRAYAGG: SQL에서 여러 행 데이터를 JSON 배열로 모아주는 꿀 함수임. DISTINCT랑 같이 쓰면 중복도 제거할 수 있음.
  • @JsonRawValue: Jackson 라이브러리에서 제공하는 이 어노테이션이 문자열 필드를 JSON으로 변환할 때 원시 JSON으로 처리하게 해줌. 이미 JSON 형식인 문자열을 다시 이스케이프 안 하고 그대로 출력하게 해주는 거임.

 

 

 

  • @JsonRawValue 쓸 때는 해당 필드 값이 항상 유효한 JSON 형식이어야 함. 아니면 JSON 파싱 에러 날 수 있음.
  • 보안 측면에서, 사용자 입력이 직접 이 필드에 들어가면 조심해야 함. JSON 삽입 공격 가능성 있으니까, 적절한 검증이랑 이스케이프 처리가 필요할 수 있다고함