Jackson deserialization of a Lombok @Builder class using a mixin is not working

Viewed 1096

This is my class:

@Builder
@Value
public class A {
    int id;
    String name;
    @NonNull String lastName;
}

The Lombok @Builder will add the all args constructor.

I need to deserialise a string into a POJO object.

I created the following Jackson mixin containing all three properties:

public abstract class AMixin {
    public AMixin(@JsonProperty("name") String name,
                  @JsonProperty("id") int id,
                  @JsonProperty("lastName") String lastName) {
    }

    @JsonProperty("name")
    abstract String getName();

    @JsonProperty("id")
    abstract int getId();

    @JsonProperty("lastName")
    abstract String getLastName();

}

I deserialise like this:

public static void main(String[] args) throws Exception {


        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(A.class, AMixin.class);

        String ss = "{\"id\":1,\"name\":\"some name\",\"lastName\":\"some name\"}\n";
        A c = mapper.readValue(ss, A.class);
    }

but I get this error:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.bla.test.A` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"id":1,"name":"some name","lastName":"some name"}
"; line: 1, column: 2]
2 Answers

The issue here is that Jackson expects a no-argument constructor or some other configured way of creating the object.

As of Lombok v1.18.14, the @Jacksonized annotation can be added to the class with the @Builder annotation to automatically configure the builder to be used for Jackson deserialization.

@Jacksonized
@Builder
@Value
public class A {
    int id;
    String name;
    @NonNull String lastName;
}

The Lombok documentation for @Jacksonized describes this annotation in more detail:

The @Jacksonized annotation is an add-on annotation for @Builder and @SuperBuilder. It automatically configures the generated builder class to be used by Jackson's deserialization. It only has an effect if present at a context where there is also a @Builder or a @SuperBuilder; a warning is emitted otherwise.

[...]

In particular, the annotation does the following:

  • Configure Jackson to use the builder for deserialization using @JsonDeserialize(builder=_Foobar_._Foobar_Builder[Impl].class)) on the class (where Foobar is the name of the annotated class, and Impl is added for @SuperBuilder). (An error is emitted if such an annotation already exists.)
  • Copy Jackson-related configuration annotations (like @JsonIgnoreProperties) from the class to the builder class. This is necessary so that Jackson recognizes them when using the builder.
  • Insert @JsonPOJOBuilder(withPrefix="") on the generated builder class to override Jackson's default prefix "with". If you configured a different prefix in lombok using setterPrefix, this value is used. If you changed the name of the build() method using using buildMethodName, this is also made known to Jackson.
  • For @SuperBuilder, make the builder implementation class package-private.

Note: This issue has nothing to do with the usage of a mixin, which can be verified by moving Jackson configuration from the mixin to the class itself and observing that the issue is still present.

I found the answer.

Add lombok.config file with content:

lombok.anyConstructor.addConstructorProperties=true
Related