Search before asking

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

Describe the bug

If there is an ImplicitPropertyName, it seems that JsonCreator.Mode.PROPERTIES is treated as the basis.

Version Information

Both refer to the head of the branch.

  • 2.17
  • 2.18

Reproduction

Comment out findImplicitPropertyName so that it is treated as JsonCreator.Mode.DELEGATING and the test will succeed.

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.Test;

import java.util.Map;

public class GitHub846Java {
    static class Dst {
        private final Map<String, String> map;

        Dst(Map<String, String> map) {
            this.map = map;
        }

        public Map<String, String> getMap() {
            return map;
        }
    }

    // region: reproducing for 2.17
    static class AI217 extends NopAnnotationIntrospector {
        @Override
        public String findImplicitPropertyName(AnnotatedMember member) {
            // Hard coded as only Dst needs to be processed
            if (member instanceof AnnotatedParameter) {
                System.out.println(member);
                System.out.println("map");
                return "map";
            }
            return null;
        }

        @Override
        public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated ann) {
            if (ann instanceof AnnotatedConstructor) {
                AnnotatedConstructor ac = (AnnotatedConstructor) ann;
                if (ac.getParameterCount() == 1) {
                    System.out.println(ac);
                    return JsonCreator.Mode.DEFAULT;
                }
            }
            return super.findCreatorAnnotation(config, ann);
        }
    }

    @Test
    public void test217() throws JsonProcessingException {
        SimpleModule sm = new SimpleModule() {
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.appendAnnotationIntrospector(new AI217());
            }
        };
        ObjectMapper mapper = new ObjectMapper().registerModule(sm);

        Dst dst = mapper.readValue("{ \"key\":\"value\" }", Dst.class);

        System.out.println(dst.getMap());
    }
    // endregion
}

Expected behavior

Given that it is not an explicit name, I felt that the treatment of both could be the same.

Additional context

This was found in a research on the following comment https://github.com/FasterXML/jackson-module-kotlin/issues/846#issuecomment-2644486029

I was not sure if this behavior is a bug, but I submitted it because if it is fixed as a bug, the above issue may be fixed at the same time.

There also seems to be a way to treat it as JsonCreator.Mode.DELEGATING by making some changes to the reproduced code, at least in the 2.17 branch. The 2.17 branch of kotlin-module should be handled the same way as the reproduced code, but the test does not fail (this behavior seems to have been changed destructively in 2.18, and https://github.com/FasterXML/jackson-module-kotlin/issues/846 is the issue that reports it). Since it will take more time to investigate the cause of this behavior, let me first ask if the change in behavior with or without ImplicitPropertyName is the expected behavior.

Comment From: cowtowncoder

The problem is not just the implicit name (although it is required, just not sufficient), but rather there is:

        public Map<String, String> getMap() {

which makes it look very likely map is a Property to set. So this is intentional heuristics, unfortunately. If getter was missing (public Field named "map" would also cause this) heuristics would not work this way. The reason for heuristics is easier to see if we instead had, say, String name.

I don't know why 2.17 or earlier might have worked differently.

The one question there is whether heuristics should consider type Map (and perhaps JsonNode) to instead imply DELEGATING.

I think this is sort of follow-up to #4911.

Comment From: cowtowncoder

Re-reading all of above, I think that the behavior of auto-detection in 2.18 is as expected: the reason PROPERTIES mode is detected is due to implicit property name "map" (which is sufficient without being explicitly annotated name -- although explicit would force choice without matching getter/setter/field).

Users likely should not rely on auto-detection in such case, fwtw.

Closing as "work as expected".