일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Test Doulbe
- 공룡책
- enumSet
- Java
- Junit 5
- 소프티어
- 자바
- RequestBody
- MySQL
- db
- 일상
- Service 계층 테스트
- backend
- proxyFactory
- 인프콘2023
- Spring
- Server
- 테크쇼
- Test
- Test code
- ExceptionResolver
- softeer
- ObjectMapper
- Coputer Science
- JPQL
- OS
- modelmapper
- JPA
- FCM
- mapstruct
- Today
- Total
공부내용공유
java record JsonParseError (feat: requestBody) 본문
서론
현재 프로젝트에서 record를 dto로 열심히 사용중인데 처음에는 별 생각없이 아래 계층 dto로만 사용하다가
requestBody로는 왜 사용을 안하고 있었지라는 생각이 들어 코드를 바로 작성하였다.
그런데 JsonParsingError가 발생했다. requestBody 맵핑 과정 를 공부한 후라 맵핑이 안될이유가 없는데? 라고 생각을 하면서 열심히 삽질을 하여서 왜 안되는지 알게되었다.
이 글에서는 삽질 과정을 기록하기 위해 글을 작성하였다.
본론
내가 예외를 만나고 의심한 포인트들을 나열하고 간단하게 설명할 예정이다.
build
처음에 jsonParsingException이 발생한 것을 보고 build tool이 intellij인지를 확인했는데 gradle이었고 그렇다면 문제없이 mapping이 되야 했다, (필드도 여러개 있던 record였다.)
만약 해당 말이 무슨 말인지 잘 모르겠다면 서론에 링크를 걸어둔 requestBody 맵핑 과정 글에 잘 나와있다.
record 바이트 코드
그 다음에는 record가 변환될 때 내가 알고있는 방식과 다르게 작동하나? 라고 생각을 하면서 byte code를 확인해보았다.
사진에서도 볼 수 있듯이 둘 다 2개 이상의 private final 필드로 선언되고 모든 필드를 가진 생성자가 만들어진다.
그런데 일반 class는 예외 없이 mapping이 잘 되는데 record의 경우에는 mapping이 안된다...
@JsonCreator, @JsonProperty
왜그럴까 왜그럴까를 반복하면서 지푸라기라도 잡는 심정으로 @JsonCreator와 @JsonPropery를 record에 써보았다.
public ItemUpdateRequestR(
@JsonProperty("item_price") Integer itemPrice,
@JsonProperty("stock") Integer stock,
@JsonProperty("itemName") String itemName,
@JsonProperty("bookable") Boolean bookable) {
this.itemPrice = itemPrice;
this.stock = stock;
this.itemName = itemName;
this.bookable = bookable;
}
결과는 mapping이 잘 됐다.. 정확히는 @JsonCreator는 필요 없고 @JsonProperty만 작성해주면 됐다. (어자피 생성자는 1개니까)
왜 이렇게 해야 하는지 열심히 구글링 하다가 나와 같은 문제에 봉착한 사람의 질문글을 보았다.
뭐가 문제였을까?
현재 프로젝트에서 api 스펙은 모두 - 를 사용한다 (item-name, item-price) 그리고 이를 맞춰주기 위해 objectMapper에 snakeCaseStrategy
를 사용하고 있다.
문제는 여기에서 발생하고 있었다. camelCase로 json을 작성하고 요청을 하면 mapping이 잘 되었다..
jackson databind에서 record에 대해서는 mapping 전략을 잘 적용하지 못하고 있었던 것이다. 해당사항 이슈
그리고 이는 discussion 에서 볼 수 있듯이 2.15 버전부터 해결되었다고 한다.
그래서 2.15 버전에서 한번 확인을 해보았다.
@PatchMapping("/{id}/r")
public String updateItemByRecord(
@PathVariable Long id,
@RequestBody ItemUpdateRequestR request
){
return request.toString();
}
public record ItemUpdateRequestR(
Integer itemPrice,
Integer stock,
String itemName,
Boolean bookable
) {
}
아주 잘된다 bb
결론
자 그래서 해결책을 요약하자면
- 각 DTO마다 이름에 맞게 @JsonProperty 추가하기
- jackson 2.15로 버전 업하기
이다!!
해당 삽질 덕분에 복습도 잘 하고 record에 대한 이해도도 높아졌다! 그래도 이 글을 보는 사람들은 삽질을 덜 했으면 좋겠다!
'Spring > Spring MVC' 카테고리의 다른 글
@EnableWebMvc, WebMvcAutoConfiguration, WebMvcConfigurationSupport 알아보기 (0) | 2024.02.07 |
---|---|
RequestBody는 기본생성자가 필요없다.(feat: ParameterNamesModule) (1) | 2024.01.07 |
Spring 더 나은 예외처리 (0) | 2023.08.29 |