jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

Lombok `@Builder.Default` no longer applied during Jackson 3 deserialization

Open ditogam opened this issue 4 weeks ago • 3 comments

Lombok @Builder.Default no longer applied during Jackson 3 deserialization

Summary

In Jackson 2.x, Lombok’s @Builder.Default values were automatically preserved during deserialization.
In Jackson 3.x, these defaults are no longer applied, and missing fields now become null.

I would like to understand whether this is an intentional design change or a regression, and what the recommended modern approach is.


Example (Jackson 2 behavior)

The following class worked correctly in Jackson 2.x:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DisplayConfigUpdate {
    .........................................
    @Builder.Default
    private Boolean isPrimary = true;
    .........................................
}

If the JSON omitted "isPrimary", Jackson 2 populated isPrimary with the default value true.


Jackson 3 behavior

With Jackson 3, the same class results in isPrimary = null when the field is missing from JSON.
The default value defined in the builder is ignored.

The only way I was able to restore the old behavior was to manually override the builder like this:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonDeserialize(builder = DisplayConfigUpdate.class)
public class DisplayConfigUpdate {
    .........................................
    @Builder.Default
    private Boolean isPrimary = true;
    .........................................
    public DisplayConfigUpdate build() {
        if (isPrimary == null) {
            isPrimary = true;
        }
        return this;
    }
}

This works, but it defeats the purpose of Lombok’s builder defaults and adds unnecessary boilerplate.


Expected behavior

Jackson 3 should behave like Jackson 2 (unless intentionally changed):

  • When a field annotated with @Builder.Default is missing from JSON
  • The default value defined in the builder initializer should be assigned during deserialization

Actual behavior

  • Jackson 3 passes null to the builder for missing fields
  • Lombok’s default value is not applied
  • The only working solution is manually overriding build() and restoring defaults

Questions

  1. Is this change intentional in Jackson 3?
  2. Should @Builder.Default still work the same way, or is there a new recommended pattern?
  3. If this is a regression, can support for Lombok builder defaults be restored?

Thank you.

ditogam avatar Nov 25 '25 12:11 ditogam

Wrong repo: will transfer.

cowtowncoder avatar Nov 25 '25 17:11 cowtowncoder

We do not accept Lombok-based reproductions, will need de-Lombokified reproduction. It is not really possible to say much about the issue without such reproduction.

cowtowncoder avatar Nov 25 '25 17:11 cowtowncoder

NOTE: it seems likely that Lombok is using "wrong" @JsonDeserialize annotation: since this annotation is part of jackson-databind artifact -- and not shared jackson-annotations -- it needs to be Jackson 3.x (tools.jackson.databind.annotations.JsonDeserialize or such) not 2.x.

If so, this is something for Lombok to handle.

cowtowncoder avatar Nov 26 '25 02:11 cowtowncoder

Needs handling on Lombok side, closing.

cowtowncoder avatar Dec 18 '25 02:12 cowtowncoder