Skip to content

@JsonSetter(nulls = Nulls.SKIP) doesn't work in some situations #4441

@Asapin

Description

@Asapin

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

We're using @JsonSetter(nulls = Nulls.SKIP) quite heavily in our code base to avoid dealing with null values, but yesterday I noticed that some fields contain null despite being annotated with @JsonSetter(nulls = Nulls.SKIP)

Version Information

2.15.3, 2.15.4, 2.16.0, 2.16.1, 2.16.2, 2.17.0

Reproduction

public class Main {
    static class Outer {
        @JsonSetter(nulls = Nulls.SKIP)
        private final List<Middle> list1 = new ArrayList<>();

        public Outer() {
        }

        public List<Middle> getList1() {
            return list1;
        }
    }

    static class Middle {
        @JsonSetter(nulls = Nulls.SKIP)
        private final List<Inner> list1 = new ArrayList<>();
        private final String field1;

        @ConstructorProperties({"field1"})
        public Middle(String field1) {
            this.field1 = field1;
        }

        public List<Inner> getList1() {
            return list1;
        }

        public String getField1() {
            return field1;
        }
    }

    static class Inner {
        private final String field1;

        @ConstructorProperties({"field1"})
        public Inner(String field1) {
            this.field1 = field1;
        }

        public String getField1() {
            return field1;
        }
    }

    public static void main(String[] args) {
        String json = """
                {
                    "list1": [
                        {
                            "list1": null,
                            "field1": "data"
                        }
                    ]
                }
                """;
        ObjectMapper objectMapper = new ObjectMapper();
        Outer outer;
        try {
            outer = objectMapper.readValue(json, Outer.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        validateNotNull(outer);
        validateNotNull(outer.getList1());
        for (Middle middle : outer.getList1()) {
            validateNotNull(middle);
            validateNotNull(middle.getField1());
            validateNotNull(middle.getList1());
        }
    }

    private static void validateNotNull(Object o) {
        if (o == null) {
            throw new IllegalStateException("Shouldn't be null");
        }
    }
}

Expected behavior

middle.getList1() shouldn't be null since it's annotated with @JsonSetter(nulls = Nulls.SKIP)

Additional context

Any of the following seems to fix the issue, but is not really feasible to do:

  • Change the order of fields in the JSON:
{
    "list1": [
        {
            "field1": "data",
            "list1": null
        }
    ]
}
  • Remove final from Middle#field1 and remove this field from constructor parameters

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.17Issues planned at earliest for 2.17

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions