Skip to content

If there is a no-parameter constructor marked as JsonCreator and a constructor reported as DefaultCreator, latter is incorrectly used. #5045

Description

@k163377

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

If both JsonCreator and DefaultCreator are reported, the JsonCreator should take precedence.
On the other hand, in certain cases, the DefaultCreator may take precedence.

This issue is a Javaized version of the following
FasterXML/jackson-module-kotlin#932
#5040

Version Information

  • 2.19.0-SNAPSHOT
  • Probably the same for 2.18.3.

Reproduction

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.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.PotentialCreator;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.Test;

import java.util.List;

public class Kotlin932Java {
    static class User {
        private final int age;

        public User(int age) { this.age = age; }

        @JsonCreator
        public User() { this(0); }

        public int getAge() { return age; }
    }

    static class AI extends NopAnnotationIntrospector {
        @Override
        public PotentialCreator findDefaultCreator(MapperConfig<?> config,
                                                   AnnotatedClass valueClass,
                                                   List<PotentialCreator> declaredConstructors,
                                                   List<PotentialCreator> declaredFactories) {
            if (valueClass.getRawType() != User.class) return null;

            return declaredConstructors.stream()
                    .filter(it -> it.paramCount() != 0)
                    .findFirst()
                    .orElse(null);
        }
    }

    @Test
    public void kotlin932() throws JsonProcessingException {
        ObjectMapper mapper = JsonMapper.builder().annotationIntrospector(new AI()).build();
        String json =
                "{\n" +
                "  \"age\": 25\n" +
                "}";

        User user = mapper.readValue(json, User.class);

        System.out.println(user);
    }
}

Expected behavior

Deserialization should succeed, but in fact has no property name ... is reported.

Additional context

The full stack trace when run on the 2.19 branch of kotlin-module.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `com.fasterxml.jackson.module.kotlin.test.github.Kotlin932Java$User`: Argument #0 of Creator [constructor for `com.fasterxml.jackson.module.kotlin.test.github.Kotlin932Java$User` (1 arg), annotations: [null] has no property name (and is not Injectable): can not use as property-based Creator
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]

	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:62)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadTypeDefinition(DeserializationContext.java:1893)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addSelectedPropertiesBasedCreator(BasicDeserializerFactory.java:535)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:259)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:209)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:263)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:152)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:472)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:416)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:318)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:285)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:175)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:669)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:5102)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4972)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3887)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3855)
	at com.fasterxml.jackson.module.kotlin.test.github.Kotlin932Java.kotlin932(Kotlin932Java.java:50)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions