Search before asking

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

Describe the bug

Continuation of https://github.com/FasterXML/jackson-databind/issues/4922.

Version Information

2.19.1, 2.19.2, 2.18.3

Reproduction

When the containing class of the Map is constructed with a @JsonCreator constructor, the issue comes back.

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonMerge;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;

interface MyMap<K, V> extends Map<K, V> {}

class MapImpl<K, V> extends HashMap<K, V> implements MyMap<K, V> {}

class MapUtils {

    static <K, V> MyMap<K, V> createMyMap() {
        return new MapImpl<K, V>();
    }
}

class MergeMap {

    @JsonCreator
    MergeMap(int inter, String s) {
        System.out.println("creator for " + map.getClass().getSimpleName());
        this.inter = inter;
        this.s = s;
    }

    int inter;
    String s;

    public int getInter() {
        return inter;
    }

//  public String getS() {
//      return s;
//  }

    @JsonMerge
    MyMap<Integer, String> map = MapUtils.createMyMap();

    public MyMap<Integer, String> getMap() {
        System.out.println("getMap");
        return map;
    }

    @Override
    public String toString() {
        return map.toString() + " " + inter + " " + s;
    }

    public static void main(String[] args) throws Exception {
        JsonMapper MAPPER = JsonMapper.builder()
                .addModule(new ParameterNamesModule())
                .configure(Feature.INCLUDE_SOURCE_IN_LOCATION, true)
                .build();

        var merge = new MergeMap(5, "f");
        merge.getMap().put(3, "ADS");
        System.out.println(merge);

        System.out.println(" == serializing --");

        var string = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(merge);
        System.out.println(string);

        System.out.println(" == deserializing --");

        var merge2 = MAPPER.readValue(string, MergeMap.class);

        System.out.println(" == checking --");

        System.out.println(merge2);
    }
}

Gives

creator for MapImpl
getMap
{3=ADS} 5 f
 == serializing --
getMap
{
  "inter" : 5,
  "map" : {
    "3" : "ADS"
  }
}
 == deserializing --
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `example.MyMap` (no Creators, like default constructor, exist): no default constructor found
 at [Source: (String)"{
  "inter" : 5,
  "map" : {
    "3" : "ADS"
  }
}"; line: 3, column: 11] (through reference chain: example.MergeMap["map"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1915)
    at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:415)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1402)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:440)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:31)
    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._deserializeUsingPropertyBased(BeanDeserializer.java:480)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1499)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:340)
    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 example.MergeMap.main(MergeMap.java:74)

Uncommenting the getS() method resolves the issue, but shouldn't have affected the construction of the map. Also, declaring Map<Integer, String> map = MapUtils.createMyMap(); instead also works, but the whole point is to merge to an initialized custom type. It shows that the containing class construction is valid, however.

Expected behavior

No response

Additional context

No response