jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

@JsonUnwrapped can't handle name collision

Open phraktle opened this issue 6 months ago • 1 comments

Search before asking

  • [x] I searched in the issues and found nothing similar.

Describe the bug

The code below yields an exception:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `UnwrappedTest$Foo` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1)
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 6] (through reference chain: UnwrappedTest$Bar["a"])
        at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
        at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1781)
        at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1406)
        at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromInt(ValueInstantiator.java:337)
        at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromInt(StdValueInstantiator.java:398)
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromNumber(BeanDeserializerBase.java:1541)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:191)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:179)
        at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:543)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:587)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeUsingPropertyBasedWithUnwrapped(BeanDeserializer.java:881)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithUnwrapped(BeanDeserializer.java:736)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:335)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
        at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4971)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3887)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3855)
        at UnwrappedTest.main(UnwrappedTest.java:15)

Version Information

2.19.0

Reproduction

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.json.JsonMapper;

public class UnwrappedTest {

    record Foo(int a, int b) {}

    record Bar(@JsonUnwrapped Foo a, int c) {}

    public static void main(String[] args) throws IOException {
        var m = new JsonMapper();
        var bar = m.writeValueAsString(new Bar(new Foo(1, 2), 3));
        var b = m.readValue(bar, Bar.class);
        System.err.println(b);
    }

}

Expected behavior

It should just work.

If Bar#a is renamed, eg. to foo, the code passes.

Additional context

No response

phraktle avatar Apr 25 '25 22:04 phraktle