Unable to deserialize when using new Record classes

The compiler generates the constructor and other accessor method for a Record.

In your case,

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

Here you can see that there is not default constructor which is needed got Jackson. The constructor you used is a compact constructor,

public Post {
 }

You can define a default/no args constructor as,

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

But Jackson uses Getter and Setters to set values. So in short, you can not use Record for mapping the response.


EDIT as PSA: Jackson can properly serialize and deserialize records as of 2.12 which has been released.


It is possible with some Jackson Annotations, which cause Jackson to use fields instead of getters. Still far less verbose than a pre-Java 14 class (without Lombok or similar solutions).

record Foo(@JsonProperty("a") int a, @JsonProperty("b") int b){
}

This probably works because according to https://openjdk.java.net/jeps/359:

Declaration annotations are permitted on record components if they are applicable to record components, parameters, fields, or methods. Declaration annotations that are applicable to any of these targets are propagated to implicit declarations of any mandated members.

See also: When is the @JsonProperty property used and what is it used for?

It is also possible to make use @JsonAutoDetect

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
record Bar(int a, int b){
}

If configuring the Objectmapper to use field Visibility globally, this annotation on class level is not needed.

See also: How to specify jackson to only use fields - preferably globally

Example:

public class Test {
    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper om = new ObjectMapper();
        System.out.println(om.writeValueAsString(new Foo(1, 2)));  //{"a":1,"b":2}
        System.out.println(om.writeValueAsString(new Bar(3, 4)));  //{"a":3,"b":4} 
    }

    record Foo(@JsonProperty("a") int a, @JsonProperty("b") int b){
    }

    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
    record Bar(int a, int b){
    }
}

There is also a Github issue for that feature: https://github.com/FasterXML/jackson-future-ideas/issues/46


This is slated for jackson 2.12

https://github.com/FasterXML/jackson-future-ideas/issues/46