Spring

새 레코드 클래스를 사용할 때 역직렬화할 수 없음

기록만이살길 2022. 12. 4. 23:36
반응형

새 레코드 클래스를 사용할 때 역직렬화할 수 없음

1. 질문(문제점):

Java 14의 새 레코드 클래스로 기존 Pojo를 대체할 수 있는지 확인하려고 합니다. 하지만 그렇게 할 수 없습니다. 다음 오류 발생:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 인스턴스를 구성할 수 없음 com.a.a.Post(기본 구성과 같은 생성자가 존재하지 않음): 개체 값에서 역직렬화할 수 없음(대리인 또는 속성 기반 생성자 없음)

레코드에 생성자가 없다는 오류가 발생했지만 레코드 클래스가 백그라운드에서 처리하고 관련 게터도 백그라운드에서 설정됩니다(정확히 게터가 아니라 id() title() 등). get 접두사 없이 켜짐). Spring이 아직 최신 Java 14 레코드를 채택하지 않았기 때문입니까? 조언 부탁드립니다. 감사.

Spring Boot 버전 2.2.6에서 Java 14를 사용하여 이 작업을 수행하고 있습니다.

다음은 일반적인 POJO를 사용하여 작동합니다.

PostClass

public class PostClass {
    private int userId;
    private int id;
    private String title;
    private String body;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

위의 POJO를 사용하면서 현재 작동하는 휴식 서비스를 호출하는 방법입니다.

public PostClass[] getPosts() throws URISyntaxException {
    String url = "https://jsonplaceholder.typicode.com/posts";
    return template.getForEntity(new URI(url), PostClass[].class).getBody();
}

그러나 대신 레코드를 사용하는 위치로 전환하면 위의 오류가 발생합니다.

새로운 레코드 클래스.

public record Post(int userId, int id, String title, String body) {
}

실패한 대신 레코드를 사용하도록 방법을 변경합니다.

public Post[] getPosts() throws URISyntaxException {
    String url = "https://jsonplaceholder.typicode.com/posts";
    return template.getForEntity(new URI(url), Post[].class).getBody();
}

편집하다:

레코드 Post 및 동일한 오류에 다음과 같이 생성자를 추가하려고 시도했습니다.

public record Post(int userId, int id, String title, String body) {
    public Post {
    }
}

또는

public record Post(int userId, int id, String title, String body) {
    public Post(int userId, int id, String title, String body) {
        this.userId = userId;
        this.id = id;
        this.title = title;
        this.body = body;
    }
}

2. 해결방안:

컴파일러는 레코드에 대한 생성자와 기타 접근자 메서드를 생성합니다.

귀하의 경우,

  public final class Post extends java.lang.Record {  
  public Post(int, int java.lang.String, java.lang.String);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public int userId();
  public int id();
  public java.lang.String title();
  public java.lang.String body();
}

여기에서 Jackson이 필요한 기본 생성자가 없음을 알 수 있습니다. 사용한 생성자는 소형 생성자입니다.

public Post {
 }

default/no args 생성자를 다음과 같이 정의할 수 있습니다.

public record Post(int userId, int id, String title, String body) {
    public Post() {
        this(0,0, null, null);
    }
}

그러나 Jackson은 Getter 및 Setters를 사용하여 값을 설정합니다. 즉, 응답을 매핑하기 위해 레코드를 사용할 수 없습니다.


PSA로 편집: Jackson은 릴리스된 2.12부터 레코드 를 올바르게 직렬화 및 역직렬화할 수 있습니다 .

반응형