스프링은 RequestResponseBodyMethodProcessor(ArgumentResolver)가 MappingJackson2HttpMessageConvertor를 이용해서 역직렬화를 수행하는데, 이때 기본적으로는 기본 생성자로 DTO를 생성해서 기본생성자가 필요합니다. 하지만 @JsonProperty, @JsonAutoDetect 등을 이용한 Property 기반 클래스이거나, 생성자가 위임된 경우라면 필요하지 않습니다. 하지만 다음과 같이 애노테이션을 사용하면 문제가 될 수 있는게, 명시된 기본 생성자가 없을 때 @Builder 애노테이션을 사용하면 @AllArgsConstructor(access = AccessLevel.PRIVATE)이 붙게 됩니다. 따라서 기본 생성자가 만들어지지 않고, 역직렬화 시 기본 생성자가 없어 역직렬화 에러가 발생합니다.
@Builder를 제거해주면 됩니다. 리플렉션을 사용해 필드에 값을 넣어주므로, @Getter와 @Setter 둘 중 하나만 있으면 됩니다.
기본적으로 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이면 직렬화가 가능합니다)
저 문제가 원인일 수도 있고, 아닐 수도 있는 것 같더라고요.. 그래서 정리해봤습니다.
틀린 부분 있으면 피드백 부탁드립니다!
@RequestBody
파라미터에
@RequestBody
가 있으면스프링은
RequestResponseBodyMethodProcessor(ArgumentResolver)
가MappingJackson2HttpMessageConvertor
를 이용해서 역직렬화를 수행하는데,이때 기본적으로는 기본 생성자로 DTO를 생성해서 기본생성자가 필요합니다.
하지만
@JsonProperty, @JsonAutoDetect
등을 이용한Property
기반 클래스이거나, 생성자가 위임된 경우라면 필요하지 않습니다.하지만 다음과 같이 애노테이션을 사용하면 문제가 될 수 있는게, 명시된 기본 생성자가 없을 때
@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