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:
- Only one constructor
- That constructor is visible (by default,
public
) - 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.