java - 使用新的 Record 类时无法反序列化

标签 java spring spring-boot java-14 java-record

我想看看我是否可以用 Java 14 中的新 Record 类替换我现有的 Pojo。但无法这样做。得到以下错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.a.a.Post (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)



我知道错误是说记录没有构造函数,但是从我所看到的记录类在后台处理它,并且相关的 getter 也在后台设置(不完全是 getter,而是 id() title() 等等没有 get 前缀)。是不是因为 Spring 还没有采用最新的 Java 14 记录?请指教。谢谢。

我在 Spring Boot 版本 2.2.6 中执行此操作并使用 Java 14。

以下使用通常的 POJO 工作。

邮政类
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;
    }
}

调用 rest 服务的方法,现在我正在使用上述 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;
    }
}

最佳答案

编译器为 Record 生成构造函数和其他访问器方法。
在你的情况下,

  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 {
 }
您可以将默认/无参数构造函数定义为,
public record Post(int userId, int id, String title, String body) {
    public Post() {
        this(0,0, null, null);
    }
}
但是 Jackson 使用 Getter 和 Setter 来设置值。所以简而言之,您不能使用 Record 来映射响应。

编辑为 PSA: Jackson can properly serialize and deserialize records as of 2.12 which has been released

关于java - 使用新的 Record 类时无法反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61140857/

相关文章:

java - Spring 中的两个 UserDetailsS​​ervices,Java 配置

spring-boot - 正确的SearchQuery的几个参数-Elasticsearch和Spring Boot

java - Postgresql jdbc 驱动程序与 EDB 驱动程序

java - Spring 3.2 - 切换到 JavaConfig 后无法解析 View 名称

Java全屏独占模式

java - 如何模拟离线 Spring Boot 应用程序

java - PubSubInboundChannelAdapter 在收到第四条消息后停止接收消息

java - 使用依赖注入(inject)连接多个配置类

java - PHP 相当于 Java 中的 getBytes

java - 从 tomcat 服务器中的 war 文件运行 java 类