API 통신을 하다 보면 대부분 JSON 형태로 데이터를 주고받는다.
이때, 서로 파라미터 작성 방식(카멜케이스,스네이크케이스) 또는 파라미터 명이 다를 경우 데이터를 파싱 하는 도중에 에러 또는 원활하게 파싱이 되지 않는 경우가 있다.
0. 카멜 케이스, 스네이크 케이스
- 카멜 케이스(Camel Case)
- 첫 글자는 소문자로, 중간 글자들은 대문자로 시작하는 표기법
- ex) memberId, memberName, memberPhoneNumber
- 스네이크 케이스(Snake Case)
- 첫 글자는 소문자로, 중간 글자들은 언더바(_)가 포함되는 표기법
- ex) member_id, member_name, member_phone_number
1. 코드
- 간단하게 Json 형태로 Request 를 전달받는 코드를 작성해보겠습니다.
// UserRequestDto
@Getter
@Setter
@ToString
public class UserRequestDto {
private String memberId;
private String memberName;
private String member_phone_number;
private String zipCode;
}
@RestController
@RequestMapping("/api")
class PostApiController {
@PostMapping("/test")
public UserRequestDto postMappingObject(@RequestBody UserRequestDto request) {
System.out.println(request.toString());
return request;
}
}
- 로컬을 띄운 후 PostMan 으로 데이터를 세팅해서 테스트를 해보도록 하겠습니다.
- 위 사진에서와 같이 memberPhoneNumber 로 요청한 데이터는 member_phone_number 파라미터로 저장이 되지 않는 것을 확인할 수 있습니다.
- 이유는 요청한 key 이름(memberPhoneNumber)와 응답 객체(member_phone_number)의 파라미터 명이 다르기 때문에 발생한 문제입니다.
- 이를 해결하기 위해 @JsonProperty, @JsonNaming 을 사용해서 해결을 할 수 있습니다.
2. @JsonProperty, @JsonNaming
- 해당 어노테이션을 사용하기 위해서는 Jackson 라이브러리를 사용해야 합니다.
- com.fasterxml.jackson.core 패키지를 dependency 에 추가합니다.
- Maven
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.2</version>
<type>bundle</type>
</dependency>
- Gradle
implementation 'com.fasterxml.jackson.core:jackson-core:2.13.2'
참고!!!
스프링부트를 사용하실 경우 아래 Dependency에 위 패키지가 포함되어 있어, 따로 추가하실 필요는 없습니다!!!
(혹여나 특정 버전이 필요하실 경우에는 따로 추가하셔도 됩니다.)
implementation 'org.springframework.boot:spring-boot-starter-web'
2-1. @JsonProperty
- 해당 어노테이션은 객체를 JSON 형식으로 변환할 때 Key의 이름을 설정할 수 있습니다.
- 위 테스트에서 실패한 member_phone_number 변수에 해당 어노테이션을 추가하여 다시 확인해보겠습니다.
// UserRequestDto
@Getter
@Setter
@ToString
public class UserRequestDto {
private String memberId;
private String memberName;
@JsonProperty("memberPhoneNumber")
private String member_phone_number;
private String zipCode;
}
- 위 사진에서와 같이 이번에는 memberPhoneNumber 까지 정상적으로 파싱 되어 전달된 것을 확인할 수 있습니다.
- 그러나, 1~2개 정도인 경우에는 해당 어노테이션을 사용하여 해결할 수 있겠지만, 10~20개 이상이 된다면 필드 하나하나 추가하는 것은 코드도 길어지고 유지보수 면에서도 번거로운 작업이 됩니다.
- 이럴 때에 사용하는 것이 @JsonNaming 어노테이션입니다.
2-2. @JsonNaming
- 위에서 사용했던 Dto를 아래와 같이 모두 카멜 케이스로 작성하고, @JsonNaming 어노테이션을 통해 모두 스네이크 케이스로 전달받을 수 있습니다.
@Getter
@Setter
@ToString
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequestDto {
private String memberId;
private String memberName;
private String memberPhoneNumber;
private String zipCode;
}
- PostMan 에서도 모두 스네이크 케이스 형태로 작성하여 Request 를 보냅니다.
- 정상적으로 데이터 파싱 된 것을 확인할 수 있습니다.
참고!!!
위 응답 값을 확인해보면, Dto에는 카멜케이스로 작성되어 있는데, 응답 값은 스네이크케이스로 되어 전달되고 있는 것을 확인할 수 있다.(로그 상에서는 정상적으로 카멜케이스로 보여짐)
이는 @JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) 에서 SnakeCaseStrategy.class 에서 해당 dto 파일의 필드(변수)들을 스네이크케이스 형태로 바꿔서 사용하기 때문이다.
(return 값에서 UserReuqestDto 을 그대로 사용하여 Return 시에도 SnakeCaseStrategy에 의해 스네이크 케이스로 변환되어 전달된다.
정상적인 개발에서는 ResponseDto 를 따로 개발하여 사용할 것이다.)
- 아래 이미지는 @JsonNaming 어노테이션에 적용하는 PropertyNamingStrategies.class 아래 SnakeCaseStrategy static 클래스이다.
package com.fasterxml.jackson.databind;
public abstract class PropertyNamingStrategies implements java.io.Serializable
{
private static final long serialVersionUID = 2L;
/*
/**********************************************************************
/* Static instances that may be referenced
/**********************************************************************
*/
...
public static class SnakeCaseStrategy extends NamingBase
{
private static final long serialVersionUID = 2L;
@Override
public String translate(String input)
{
if (input == null) return input; // garbage in, garbage out
int length = input.length();
...
}
...
}
참고
'BackEnd' 카테고리의 다른 글
MyBatis(마이바티스)에서 사용하는 WHERE 1=1 의 위험성 및 예방(Feat. 장애) (0) | 2022.09.18 |
---|---|
[Heroku] SpringBoot + MySQL(heroku) 배포하기 - (2)Heroku 배포 (0) | 2022.04.23 |
[Heroku] SpringBoot + MySQL(heroku) 배포하기 - (1)Heroku 설정 (0) | 2022.04.23 |
[Server] REST API 란? (0) | 2022.04.06 |
프로젝트 Github 연동하기(with Source Tree) (0) | 2021.03.28 |