有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在使用新记录类时无法反序列化

我试图看看是否可以用Java14中的新记录类替换现有的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还没有采用最新的Java14记录吗?请给出建议。谢谢

我在Spring Boot版本2.2.6中使用Java14实现了这一点

以下是使用常用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();
}

但如果我切换到使用record的地方,就会出现上述错误

新唱片班

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();
}

编辑:

尝试按如下方式向记录帖子中添加构造函数,但出现了相同的错误:

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;
    }
}

共 (3) 个答案

  1. # 2 楼答案

    If a public accessor method or (non-compact) canonical constructor is declared explicitly, then it only has the annotations which appear on it directly; nothing is propagated from the corresponding record component to these members.

    https://openjdk.java.net/jeps/384

    所以加上

    new ObjectMapper().registerModules(new ParameterNamesModule())
    

    试试看

    @JsonCreator record Value(String x);
    

    或者类似的

    record Value(String x) {
    
    @JsonCreator
    public Value(String x) {
    this.x = x;
    }
    }
    

    或者一路去

    record Value(@JsonProperty("x") String x) {
    
    @JsonCreator
    public Value(@JsonProperty("x") String x) {
    this.x = x;
    }
    }
    

    这就是我让lombok和jackson的不可变Pojo工作的方式,我不明白为什么记录不能在相同的格式下工作。我的设置是Jackson parameter names module,-parameters compiler flag for java8(我认为这不是像jdk9+)、构造函数上的@JsonCreator所必需的)。使用此设置的真实类的示例

    @Value
    @AllArgsConstructor(onConstructor_ = @JsonCreator)
    public final class Address {
    
      private final String line1;
    
      private final String line2;
    
      private final String city;
    
      private final String region;
    
      private final String postalCode;
    
      private final CountryCode country;
    }
    
  2. # 3 楼答案

    编译器为记录生成构造函数和其他访问器方法

    就你而言

      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();
    }
    

    在这里你可以看到没有默认的构造函数是必需的。您使用的构造函数是一个紧凑的构造函数

    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 records2.12 which has been released开始