인프런 커뮤니티 질문&답변

euichan293님의 프로필 이미지

작성한 질문수

생산성을 향상시키는 스프링부트 기반의 API 템플릿 프로젝트 구현

API 문서화 (2) - Swagger를 이용한 API 문서화

자주 나오는 질문 - DTO에 @Allargs, @Noargs 문제

작성

·

731

·

수정됨

0

스크린샷 2023-04-26 오후 1.31.07.png실행할 때 IntelliJ IDEA 가 아닌 Gradle로 돌려야 합니다

답변 1

0

구파고님의 프로필 이미지
구파고
지식공유자

해당 질문이 많이 나와서, 찾아 봤었는데 버전이나 환경, 세팅에 따라서 다른것 같고, 추가적인 어노테이션을 붙이는걸로 가이드 드렸었는데 원인이 저 부분이었군요!!

 

공유해주셔서 감사합니다. 다른분들한테도 많이 도움이 될꺼 같네요!

euichan293님의 프로필 이미지
euichan293
질문자

저 문제가 원인일 수도 있고, 아닐 수도 있는 것 같더라고요.. 그래서 정리해봤습니다.

틀린 부분 있으면 피드백 부탁드립니다!


@RequestBody

파라미터에 @RequestBody가 있으면

스프링은 RequestResponseBodyMethodProcessor(ArgumentResolver)MappingJackson2HttpMessageConvertor를 이용해서 역직렬화를 수행하는데,
이때 기본적으로는 기본 생성자로 DTO를 생성해서 기본생성자가 필요합니다.
하지만 @JsonProperty, @JsonAutoDetect 등을 이용한 Property 기반 클래스이거나, 생성자가 위임된 경우라면 필요하지 않습니다.
image하지만 다음과 같이 애노테이션을 사용하면 문제가 될 수 있는게, 명시된 기본 생성자가 없을 때 @Builder 애노테이션을 사용하면 @AllArgsConstructor(access = AccessLevel.PRIVATE)이 붙게 됩니다.
따라서 기본 생성자가 만들어지지 않고, 역직렬화 시 기본 생성자가 없어 역직렬화 에러가 발생합니다.

@Builder를 제거해주면 됩니다.
리플렉션을 사용해 필드에 값을 넣어주므로, @Getter와 @Setter 둘 중 하나만 있으면 됩니다.

 

기본 생성자만 있고 getter 가 없다면, deserialize 불가능합니다.

https://jenkov.com/tutorials/java-json/jackson-objectmapper.html#how-jackson-objectmapper-matches-json-fields-to-java-fields
다음 글을 찾아보면,

기본적으로 Jackson은 JSON 필드의 이름을 Java 오브젝트의 getter 및 setter 메서드와 일치시켜 JSON 오브젝트의 필드를 Java 오브젝트의 필드에 매칭합니다. Jackson은 getter 및 setter 메서드 이름의 "get" 및 "set" 부분을 제거하고 나머지 이름의 첫 문자를 소문자로 변환합니다.

예를 들어 brand라는 JSON 필드는 getBrand() 및 setBrand() 라는 Java getter 및 getter 메서드와 일치합니다. engineNumber라는 JSON 필드는 getEngineNumber() 및 setEngineNumber()라는 getter 및 setter와 일치합니다.

다른 방식으로 JSON object 필드를 Java object 필드와 일치시켜야 하는 경우 custom serializer 및 deserializer를 사용하거나 많은 Jackson Annotation 중 일부를 사용해야 합니다.
라고 나와있습니다.


@ResponseBody

객체를 Json으로 직렬화할 때는 @Getter가 필요합니다

 


(정리한 내용은 기본적으로 인스턴스 변수가 private일 때를 가정한 것입니다. Getter 없이도 public이면 직렬화가 가능합니다)

출처

https://www.one-tab.com/page/RTm8ARImR9iXDFNOnKdIzA

https://projectlombok.org/features/Builder