public static final class Example {
    // @Getter
    private final boolean isDefault;

    @java.beans.ConstructorProperties({"isDefault"})
    public Example(boolean isDefault) {
      this.isDefault = isDefault;
    }

    public boolean isDefault() {
      return this.isDefault;
    }
  }

  @Test
  void booleanPropertyWithIsPrefix() throws JsonProcessingException {
    var object = new Example(true);

    var mapper = new ObjectMapper();

    var messageString = mapper.writeValueAsString(object);
    var messageResult = mapper.readValue(messageString, Example.class);
    then(messageResult).isEqualTo(object);
  }

The object is serialized as {"default":true} and then fails to deserialize correctly.

When using new ObjectMapper:

Unrecognized field "default" (class Example), not marked as ignorable (one known property: "isDefault"])

When using new Jackson2ObjectMapperBuilder().build():

Expected :Example(isDefault=true)
Actual   :Example(isDefault=false)

I'm not sure if you would class this as a bug or as a configuration error, since you can configure your way out of this issue by setting

.visibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)

Comment From: pjfanning

We don't test Lombok. Can you provide a Java only reproducer?

Comment From: cowtowncoder

Yeah, without knowing what Lombok actually produces bytecode-wise it is impossible to know what is happening. We need de-lombok'd version.

Comment From: lbenedetto

Right, of course, sorry. I've delomboked the example class. Lombok generates a getter named isDefault() and jackson assumes that is is the prefix (like get) and default is the name of the field.

Comment From: cowtowncoder

Correct: Lombok's definition is different from Beans naming (which Jackson tries to implement)

If you want JSON property to be isDefault (not default), a

@JsonProperty("isDefault")

is needed for

public boolean isDefault();

Otherwise Lombok might also have functionality to configure things (if "default" is preferable as external name). In Jackson it is also possible to disable "is-getter" auto-detection, but doing so would then still need adding @JsonProperty annotation for isDefault() (and changing annotation Lombok adds to constructor).

Hope this helps.

Comment From: lbenedetto

For my purposes I don't care what the name is, as long as the object is able to be serialized and deserialized back to itself. I have my mapper configured to ignore unknown fields when deserializing so that I can safely remove fields and still deserialize old json, but this also hides this issue with the boolean field names.

Would it make sense to have some logic which looks at which fields are required to construct an object when deserializing, and ensures that all of them are produced by the serialization process? Perhaps behind Yet Another Option. Jackson knows (or has the ability to know) that constructing this object requires a value for a field named isDefault, so it should be able to realize that if it does not write a value for a field with that name during serialization, then something is wrong.

Something like SerializationFeature.DO_NOT_WRITE_UNKNOWN_FIELDS.

Comment From: cowtowncoder

There is already

MapperFeature.REQUIRE_SETTERS_FOR_GETTERS

which aims to do something like what you describe (if I understood it correctly).