Skip to content

2.9.4 doesn’t handle @JsonIgnored field with the same name as @JsonProperty(name) of other field #124

@silmeth

Description

@silmeth

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 @JsonIgnored 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions