Open hotire opened 8 months ago
Thank you for digging deeper.
By the way, is this a bug in KotlinModule
?
If databind
is the cause, please check there and report.
As a side note, if you are creating a Java
only sample code regarding deserialization, you need to set JsonCreator
in the constructor.
Hello.
In case of Java it succeeds.
The test code is below.
class JacksonJavaTest {
final ObjectMapper mapper = new ObjectMapper();
static class A {
private final String name;
@JsonCreator
public A(@JsonProperty("name") String name){
this.name = name;
}
}
static class B {
private final String name;
private final int age;
@JsonCreator
public B(
@JsonProperty("name")String name,
@JsonProperty("age")int age){
this.name = name;
this.age = age;
}
}
@Test
void success() throws JsonProcessingException {
final String json = "{\"name\" : \"hello\", \"age\": 12}";
mapper.readValue(json, B.class);
}
@Test // expected fail but success
void fail() throws JsonProcessingException {
final String json = "{\"name\" : \"hello\"}";
mapper.readValue(json, A.class);
}
}
I'm having the same problem when deserializing the following class:
class StringFromListGenerator(
val options: List<String> // Bug in Kotlin module: this cannot be private
) : ArgumentGenerator {
override fun generate(random: Random): String {
return options[random.nextInt(options.size)]
}
}
When I try to deserialize this from JSON:
{
"options": [
"ABC",
"DEF",
"123"
]
}
I get a misleading error message:
Cannot deserialize value of type
java.util.ArrayList<java.lang.String>
from Object value (tokenJsonToken.FIELD_NAME
)
I have been very busy for a while and do not have time to check this issue.
Personally, I think the problem is related to AnnotationIntrospector::findImplicitPropertyName
.
In kotlin-module
, it is implemented as KotlinNamesAnnotationIntrospector::findImplicitPropertyName
.
The sample code you gave us uses JsonProperty
to name it, but in kotlin-module
it is named using the above function.
In other words, the reproduced code in Java
that you gave me does not actually reproduce the behavior of kotlin-module
completely.
I have a vague recollection that a similar issue was previously posted on kotlin-module
and was closed as a duplication of a databind
or core
issue.
Your help in a more in-depth investigation may speed up the resolution of the issue.
Here is a possibly related example. I am not sure if the root cause is the same, perhaps I should open a new issue for this but this was similar enough to entice me to first post this as a comment here.
The interesting part here is the behaviour of deser into class B, which has a single field that unconventionally starts with an uppercase
data class A(
val foo: String,
)
data class B(
val Foo: String
)
data class C(
val Foo: String,
val Bar: String
)
data class D(
@JsonProperty("Foo")
val Foo: String,
)
fun main() {
val om = ObjectMapper().apply {
registerKotlinModule()
disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
}
val json = """{"foo": "bar", "Foo": "Foo", "Bar": "Bar", "a": "b"} """
om.readValue<A>(json) // Works
om.readValue<B>(json) // Fails with Exception in thread "main" ... Cannot construct instance of B` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
om.readValue<C>(json) // Works
om.readValue<D>(json) // Works
}
Search before asking
Describe the bug
Deserialization fails for class with single private accessor property.
When deserializing, a MismatchedInputException occurs.
To Reproduce
Expected behavior
A class with single private accessor property is properly deserialized.
Actual behavior
Versions
Kotlin: 1.8.0 Jackson-module-kotlin: 2.12.7 Jackson-databind: 2.12.7.1
Additional context
I tried to dig into this and discovered the flow below: (Code has been simplified)