-
-
Notifications
You must be signed in to change notification settings - Fork 181
Description
I have a data class that looks something like this:
data class DTO(@JsonProperty("name") val name: String,
@JsonIgnore val query: NonSerializableClass,
@JsonProperty("query") val rawQuery: String) {
@JsonCreator
constructor(@JsonProperty("name") name: String,
@JsonProperty("query") rawQuery: String) :
this(name, parseNonSerializableField(rawQuery), rawQuery)
}
Where NonSerializableClass
is a complicated external class that I do not want to write custom (de)serializers for, and whose instances can be easily created by parsing the rawQuery
string.
With Jackson 2.9.3 and jackson-module-kotlin
2.9.3 string of the kind {"name": "foo", "query": "bar"}
get nicely serialized into DTO
and the object created can be nicely deserialized.
But with Jackson + jackson-module-kotlin
2.9.4 I get a com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
"due to missing (therefore NULL) value for creator parameter rawQuery which is a non-nullable type" (but after a bit of fiddling with it, I found out that the real problem is that there is a @JsonIgnore val query
– with the same name as a @JsonProperty("name")
of another field).
A minimal test for this, that passes with version 2.9.3, but fails with 2.9.4, looks like this:
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Test
internal class DeserializationTest {
@Test
fun test() {
val objMapper = ObjectMapper().registerModule(KotlinModule())
// with 2.9.3 prints
// Foo(name=foo, query=NonSerializable, rawQuery=bar)
// but with 2.9.4 throws:
// com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class DeserializationTest$Foo] value failed for JSON property query due to missing (therefore NULL) value for creator parameter rawQuery which is a non-nullable type
// at [Source: (String)"{"name": "foo", "query": "bar"}"; line: 1, column: 31] (through reference chain: DeserializationTest$Foo["query"])
val deserialized: Foo = objMapper.readValue("{\"name\": \"foo\", \"query\": \"bar\"}")
println(deserialized)
val serialized = objMapper.writeValueAsString(deserialized)
// with 2.9.3 prints
// {"name":"foo","query":"bar"}
println(serialized)
}
class NonSerializable(private val field: Any?) {
override fun toString() = "NonSerializable"
}
data class Foo(@JsonProperty("name") val name: String,
@JsonIgnore val query: NonSerializable,
@JsonProperty("query") val rawQuery: String) {
@JsonCreator
constructor(@JsonProperty("name") name: String,
@JsonProperty("query") rawQuery: String): this(name, NonSerializable(rawQuery), rawQuery)
}
}
After changing the name of the non-serializable @JsonIgnore
d field query
to something else, like ignoredQuery
, it works in 2.9.4 too.
But that still looks like a bug, and I’d like not to change the API of my class (where value query
returns the non-serializable object) nor to force all places where this data class is serialized to change its JSON schema (to use another field like eg. rawQuery
instead of query
).