블로그 만들기 - InvalidDefinitionException : cannot deserialize from object value [Jackson ObjectMapper + Reflection]

HotFried·2024년 3월 21일
0

한땀한땀 정성들여 코드를 짰더니 Internal Server Error가 터졌다.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `klog.blog_project.entity.dto.UserDto$SignupRequest`
(no Creators, like default constructor, exist):
cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream);
 line: 2, column: 5]

회원가입 시 컨트롤러에서 SignupRequest dto를 파라미터로 받아야 하지만 생성을 할 수가 없다고 나온다.
-> no Creators, like default constructor, exist ......???


무엇이 문제일까?

직렬화

  • Serialize
  • Object to JSON
  • getter를 사용한다.

역직렬화

  • Deserialize
  • JSON to Object
  • default constructor를 사용한다.

Requestdto의 경우 역직렬화를 하게 되는데, 이 때 기본 생성자가 필요하다.
아래에서 조금 더 자세하게 내용을 다뤄보자.


Java Reflection

Java Reflection?
구체적인 클래스 타입을 알지 못해도, 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API

이미 로딩이 완료된 클래스에서 또 다른 클래스를 동적으로 로딩(Dynamic Loading)하여 생성자(Constructor), 멤버 필드(Member Variables) 그리고 멤버 메서드(Member Method) 등을 사용할 수 있도록 한다.


Almost all frameworks require a default(no-argument) constructor in your class because these frameworks use reflection to create objects by invoking the default constructor

기본 생성자로 객체를 생성하기 때문에 기본 생성자가 필요하다는 내용이다.


java Reflection이 가져올 수 없는 정보 중 하나가 바로 생성자의 파라미터들이다.
-> 기본 생성자가 없으면 java Reflection이 객체를 생성할 수 없다.

기본 생성자로 객체를 생성하고,
클래스의 필드 정보를 가져올 수 있으니까 객체 생성 후에 필드 값을 할당 한다!


하지만, 기본 생성자를 만들어버리면 외부에서 무분별하게 빈 객체를 생성할 수 있는 문제가 있는데 private 접근제한자를 둬서 이 문제를 해결할 수 있을 것 같다.

비슷하게 이전에 포스팅한 SpringBoot의 Entity 기본 생성자에 대한 내용도 있으니 참고하면 좋을 듯하다.
Entity의 기본 생성자


-> (요약하자면, 지연로딩(LAZY)으로 인해 생성된 프록시 객체를 사용하기 위해서는 private로 선언이 불가능하다.
기본 생성자가 private인 경우 상속 받은 클래스에서 호출이 불가능하기 때문)

profile
꾸준하게

0개의 댓글