FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.52k stars 1.38k forks source link

InvalidDefinitionException "No fallback setter/field defined for creator property" when deserializing JSON with duplicated property to single-property Record #4690

Open sseelmann opened 1 month ago

sseelmann commented 1 month ago

Search before asking

Describe the bug

Deserialzing a JSON with a duplicated property fails for a Java Record with a single property.

Version Information

2.17.2

Reproduction

import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.databind.ObjectMapper;

class JacksonDeserializationTest {

    record MyRecord(String first) {
    }

    @Test
    void test() throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        String json = """
                {
                    "first": "test@example.com",
                    "first": "test@example.com"
                }
                """;
        var value = mapper.readValue(json, MyRecord.class);
        System.out.println(value);
    }

}

Produces the following error:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No fallback setter/field defined for creator property 'first' (through reference chain: JacksonDeserializationTest$MyRecord["first"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.deser.CreatorProperty._reportMissingSetter(CreatorProperty.java:354)
    at com.fasterxml.jackson.databind.deser.CreatorProperty._verifySetter(CreatorProperty.java:341)
    at com.fasterxml.jackson.databind.deser.CreatorProperty.deserializeAndSet(CreatorProperty.java:270)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:273)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:470)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1493)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4905)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3848)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3816)
    at JacksonDeserializationTest.test(JacksonDeserializationTest.java:20)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

Expected behavior

Deserialization works, or a proper exception describing the problem (e.g. "duplicate property") is thrown.

Additional context

Workaround: Add a 2nd dummy property to the Java Record

Ofc the duplicate property in the JSON is not the default. It was detected during a penetration test when testing for parameter pollution vulnerabilities.

cowtowncoder commented 1 month ago

Thank you for reporting this issue. I think I know why it occurs, technically speaking, but not sure how to address it.

But in the meantime... to fail on duplicate property values, generally, it's enough to enable

StreamReadFeature.STRICT_DUPLICATE_DETECTION

on JsonFactory used to construct ObjectMapper / JsonMapper.

yihtserns commented 1 month ago

Quoting @cowtowncoder from https://github.com/FasterXML/jackson-core/issues/60:

...JSON specification does not make duplicate Object values strictly illegal (behavior is undefined I think)...

...checking for duplicates adds non-trivial amount of cost which for valid content is pure overhead...so...add a feature to let users request that duplicate detection is enabled...

sseelmann commented 1 month ago

Thanks for the suggestions, but I think I won't enable the STRICT_DUPLICATE_DETECTION feature because