Skip to content

Include.NON_DEFAULT regression for objects with @JsonValue #5312

@LSwiatek

Description

@LSwiatek

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

Classes which use @JsonValue
and use values which would result in empty string
and are used as fields in serializable Pojos,
and Object mapper is configured with Include.NON_DEFAULT
will result in different json values starting with version 2.18

Following test case will work fine in version 2.17.3, but will fail after upgrading to 2.18+

Note, this might be related to #4741 #4464

Version Information

2.18+

Reproduction

package com.example;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.MutableConfigOverride;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_DEFAULT;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;

public class JacksonTest {

    record StringValue(String value) {
        @Override
        @JsonValue
        public String value() {
            return value;
        }
    }
    record Pojo1(StringValue value) {
    }

    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    record Pojo2(StringValue value) {
    }


    record Pojo3(@JsonInclude(JsonInclude.Include.NON_DEFAULT) StringValue value) {
    }


    @Test
    void testSerialization() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(NON_DEFAULT);

        //might be relevant for analysis, but does not affect test outcome
        MutableConfigOverride objectStringConfigOverride = objectMapper.configOverride(String.class);
        objectStringConfigOverride.setIncludeAsProperty(JsonInclude.Value.construct(NON_NULL, NON_NULL));

        Assertions.assertAll(
                //FAIL on jackson 2.18.2 / 2.20.0
                () -> Assertions.assertEquals("{\"value\":\"\"}", objectMapper.writeValueAsString(new Pojo1(new StringValue("")))),
                //PASS
                () -> Assertions.assertEquals("{\"value\":\"\"}", objectMapper.writeValueAsString(new Pojo2(new StringValue("")))),
                //FAIL on jackson 2.18.2 / 2.20.0
                () -> Assertions.assertEquals("{\"value\":\"\"}", objectMapper.writeValueAsString(new Pojo3(new StringValue(""))))
        );
    }
}

Expected behavior

After serialization jackson should produce the same value

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    to-evaluateIssue that has been received but not yet evaluated

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions