Until version 2.17.3 Jackson was able to deserialize a number into wrapper classes such as this one:

class IntValue {

    private final int value;

    IntValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Since version 2.18 and higher (I tested 2.19.2), the following error is reported:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of test.IntValue (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (42)

This code was used to reproduce the problem, the ParameterNamesModule must be registered, and parameter names must be enabled in the compiler - both of these are done automatically in a typical spring-boot project :

        var objectMapper = new ObjectMapper();
        objectMapper.registerModule(new ParameterNamesModule());
        assertDoesNotThrow(() -> objectMapper.readValue("42", IntValue.class));

e.g. in pom.xml:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
        </plugins>
    </build>

The problem can be fixed by annotating the IntValue constructor with @JsonCreator(mode = JsonCreator.Mode.DELEGATING) or by creating a static factory method in the class annotated with @JsonCreator.

Comment From: cowtowncoder

This is unfortanely a feature, not bug -- constructor in question is auto-detected as "Properties-based", expecting JSON Object, instead of "Delegating" that you would like. This is inherently ambiguous case. Criteria for Properties-based auto-detection (that was not working pre-2.18) is:

  1. Only one constructor
  2. That constructor is visible (by default, public)
  3. Constructor parameters all have names

Besides using @JsonCreator annotation, what might work is using ConstructorDetector configuration to indicate preference for Delegating creators, so in ambiguous cases (1-argument, no explicit annotation) it'd select delegating mode. An example can be found from

src/test/java/com/fasterxml/jackson/databind/deser/creators/ConstructorDetectorTest.java

something like:

ObjectMapper mapper = JsonMapper.builder()
    .constructorDetector(ConstructorDetector.USE_DELEGATING)
    .build();

I hope this helps.

Comment From: cowtowncoder

Note: while parameter names module is required for this occur (to have Constructor parameter names available), handling is in jackson-databind: I will transfer the issue.