Auto-detection of constructor-based creator method skipped if there is an annotated factory-based creator method (regression from 2.11)
See original GitHub issueDescribe the bug
First, I am not sure whether it’s a bug or expected behavior, but I just wanted to open an issue for my understanding. Prior to Jackson 2.12.0, it was possible to bind a Number
(e.g., 42
) to a single field DTO (see example code below). Now, it throws MismatchedInputException
with this message:
Cannot construct instance of `jackson211$ExampleDto$Json` (although at least one Creator exists):
no int/Int-argument constructor/factory method to deserialize from Number value (42) at [Source: (String)"42"; line: 1, column: 1]
Version information 2.12.0
To Reproduce The code below can be used.
Some notes:
- I used jbang to switch between versions easily.
- The example Dto is the minimal version of an Immutables generated code.
- Jackson 2.11.3 uses the private constructor to deserialize
Number
to Dto object.
/// usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.fasterxml.jackson.core:jackson-annotations:2.12.0
//DEPS com.fasterxml.jackson.core:jackson-databind:2.12.0
// It prints `true` on 2.11.3.
////DEPS com.fasterxml.jackson.core:jackson-annotations:2.11.3
////DEPS com.fasterxml.jackson.core:jackson-databind:2.11.3
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Objects;
public final class jackson211 {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public static void main(String... args) throws JsonProcessingException {
int version = 1;
ExampleDto deserialize = OBJECT_MAPPER.readValue(String.valueOf(version), ExampleDto.class);
System.out.println(new ExampleDto(version).equals(deserialize));
}
static final class ExampleDto {
private final int version;
private ExampleDto(int version) {
this.version = version;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExampleDto that = (ExampleDto) o;
return version == that.version;
}
@Override
public int hashCode() {
return Objects.hash(version);
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
static ExampleDto fromJson(Json json) {
return new ExampleDto(json.version);
}
@JsonDeserialize
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE)
static final class Json {
int version;
boolean versionIsSet;
@JsonProperty
public void setVersion(int version) {
this.version = version;
this.versionIsSet = true;
}
public int getVersion() {
throw new UnsupportedOperationException();
}
}
}
}
Expected behavior
As I wrote at the beginning, I am not sure whether it’s a bug or expected behavior. If it’s a bug then, the example code should print true
instead of throwing an exception.
Additional context N/A
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:8 (5 by maintainers)
Top Results From Across the Web
Security update for jackson-databind, jackson-dataformats ...
... Auto-detection of constructor-based creator method skipped if there is an annotated factory-based creator method (regression from 2.11) ...
Read more >JsonCreator (Jackson-annotations 2.11.1 API) - javadoc.io
Marker annotation that can be used to define constructors and factory methods as one to use for instantiating new instances of the associated...
Read more >3.4.1.1 Constructor-based dependency injection - Spring
Dependency injection (DI) is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, ......
Read more >No Int/Int-Argument Constructor/Factory Method To Deserialize
Autodetection of constructorbased creator method skipped if there is an annotated factorybased creator method regression from 2.11 #.
Read more >Jackson 2.12 Most Wanted (3/5) - cowtowncoder - Medium
Annotation -less @JsonCreator (even 1-argument) ... (and static factory methods) are ambiguous: there are 2 possible “modes” of binding:.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
So, rewritten code in 2.12 (meant to work same way as before) had checks so that:
but apparently logic earlier was
so that existence of annotated factory method was the difference. Will change code to use older logic, to try to keep backwards-compatibility. This is bit tricky going forward as definition is not very crisp, but seems like the right thing to do for now.
Ok thank you for verifying these aspects. It sounds like there is an unintended change in behavior here, and I hope to look into it when I get a chance.