spring.jackson.property-naming-strategy 에 대하여

고범수·2023년 8월 7일
3

Spring Boot

목록 보기
8/12

상황

프론트 엔드가 백엔드로 Http body에 JSON 형식의 데이터를 전송한다. 이 때, JSON의 key 값이 snake case인 경우 Spring Boot 서버는 @RequestBody를 이용하여 매핑하게 되면 값이 매핑되지 않아 JSON에 대응되는 DTO객체의 필드가 null로 세팅된다. (JSON은 snake case, DTO는 camel case이기 때문)

예를 들어 아래와 같은 DTO 객체인 경우 @ReqeustBody로 받게 되면 기본적으로 camel case로 매핑된다.


public class DemoDto {
    private String demoName;
    private Long demoAge;
    
    @Override
    public String toString() {
        return "DemoDto{" +
                "demoName='" + demoName + '\'' +
                ", demoAge=" + demoAge +
                '}';
    }

    // getters and setters...
}

따라서 위처럼 camel case을 따르는 JSON 형태의 요청은 매핑이 되지만,

위와 같이 snake case를 따라는 JSON 형태의 요청은 매핑이 되지 않고 null 값이 채워짐을 알 수 있다. (각 Type의 초기값이 채워짐)

해결 방법

1. @JsonNaming

아래 코드처럼 @JsonNaming 어노테이션을 이용하면 class 단위로 매핑시의 naming strategy를 지정할 수 있다. naming strategy는 PropertyNamingStrategy.SnakeCaseStrategy.class와 같이 지정할 수 있으나 deprecated 되었으므로 더 이상 사용하지 말라고 한다.

import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@Getter
@Setter
@ToString
public class DemoDto {
    private String demoName;
    private Long demoAge;
}

대신 아래와 같이 사용하면 된다.

package com.example.demo.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Getter
@Setter
@ToString
public class DemoDto {
    private String demoName;
    private Long demoAge;
}

2. application.properties 또는 application.yml 파일에서 global strategy 설정하기

다음을 같이 application.properties에 추가하게 되면 전역적으로 jackson naming strategy가 설정된다. 1번 방법에서 설정한 @JsonNaming 어노테이션을 이용한 방법은 이 전역 설정을 Override하여 작동한다. (전역 설정보다 우선한다)

spring.jackson.property-naming-strategy=SNAKE_CASE

package com.example.demo.dto;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class DemoDto {
    private String demoName;
    private Long demoAge;
}

별도의 어노테이션 없이 전역 설정만으로 위와 같이 snake case로 매핑된 것을 볼 수 있다.

3. Dto 객체의 필드에 @JsonProperty 어노테이션을 붙이는 방법

@JsonProperty 어노테이션을 사용하면 각 필드에 별도의 JsonProperty 명을 지정할 수 있다.

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class DemoDto {
    @JsonProperty("demo_name")
    private String demoName;
    @JsonProperty("demo_age")
    private Long demoAge;
}

문제 없이 매핑된 것을 볼 수 있다. 참고로 프로퍼티 명을 지정하는 것이기에 다음과 같은 코드도 가능하다.

package com.example.demo.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class DemoDto {
    @JsonProperty("demo_name")
    private String demoName;
    @JsonProperty("JsonPropertyDemoAge")
    private Long demoAge;
}

결론

정말 특별한 경우가 아니라면 전역적으로 설정하는 2번 방법을 사용하게 될 것 같다.

0개의 댓글