Skip to content

Records with additional constructors failed to deserialize #3968

@GeorgiPetkov

Description

@GeorgiPetkov

Describe the bug
Records are not deserialized as before due to error:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Conflicting property-based creators: already had implicitly discovered creator [constructor for RecordsDeserializationTest$TestRecord (1 arg), annotations: [null], encountered another: [constructor for RecordsDeserializationTest$TestRecord (2 args), annotations: [null]
at [Source: (String)"{"a":"a", "b":"b"}"; line: 1, column: 1]

See the test below for the exact setup.

Version information
Which Jackson version(s) was this for?
2.15.0

To Reproduce

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.ConstructorDetector;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class RecordsDeserializationTest {

    private final ObjectMapper objectMapper = JsonMapper.builder()
            // commenting only this fixes the problem
            .addModules(new ParameterNamesModule())
            // commenting only this fixes the problem
            .constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
            .build();

    record TestRecord(String a, String b) {

        // uncommenting only this fixes the problem
        // @JsonIgnore
        TestRecord(String c) {
            this(c, c);
        }
    }

    @Test
    void testDeserialization() throws JsonProcessingException {
        assertEquals(
                new TestRecord("a", "b"),
                objectMapper.readValue("{\"a\":\"a\", \"b\":\"b\"}", TestRecord.class));
    }
}

Expected behavior
The exact combination of configuration is not working in version 2.15.0.
There are 4 ways to fix it:

  • remove module ParameterNamesModule
  • don't use USE_PROPERTIES_BASED constructor detection
  • add @JsonIgnore annotation to the extra constructor
  • use version 2.13.4 on which this works

Additional context
The caveat here is that I can't use explicit @JsonCreator annotation on the primary constructor on a record (or I have to implement it just to add the annotation). Ideally, you should restore the old behavior. The @JsonIgnore approach seems like a hack to me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions