FasterXML / jackson-module-kotlin

Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
Apache License 2.0
1.11k stars 175 forks source link

@JsonProperty ignored when serialising Kotlin @JvmRecord in 2.16.X #773

Open bmorris591 opened 4 months ago

bmorris591 commented 4 months ago

Search before asking

Describe the bug

When serialising the following Kotlin data class with 2.16.1 I get the wrong properties generate. This works with 2.15.4.

@JvmRecord
data class JacksonTest(
    @JsonProperty("propertyOne")
    val one: String,
    @JsonProperty("propertyTwo")
    val two: String
)

The following simple test code

fun main() {
    val mapper = JsonMapper.builder().findAndAddModules()
        .build()
        .enable(INCLUDE_SOURCE_IN_LOCATION)

    val test = JacksonTest("one", "two")
    val ser = mapper.writeValueAsString(test)
    println(ser)
    val de = mapper.readValue<JacksonTest>(ser)
    println(de)
}

Produces the following error

Exception in thread "main" com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class uk.co.borismorris.JacksonTest] value failed for JSON property propertyOne due to missing (therefore NULL) value for creator parameter one which is a non-nullable type
 at [Source: (String)"{"one":"one","two":"two"}"; line: 1, column: 25] (through reference chain: uk.co.borismorris.JacksonTest["propertyOne"])
    at com.fasterxml.jackson.module.kotlin.KotlinValueInstantiator.createFromObjectWith(KotlinValueInstantiator.kt:101)
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:526)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1493)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4899)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3846)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3829)
    at uk.co.borismorris.JacksonTestKt.main(JacksonTest.kt:30)
    at uk.co.borismorris.JacksonTestKt.main(JacksonTest.kt)

As you can see, the property is called one etc, not propertyOne.


Removing @JvmRecord causes the test to pass. This works correctly with @JvmRecord in 2.15.4.


Versions

Java: GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30) Kotlin: 1.9.22 (jvmTarget 21) Jackson BOM: 2.16.1

To Reproduce

fun main() {
    val mapper = JsonMapper.builder().findAndAddModules()
        .build()
        .enable(INCLUDE_SOURCE_IN_LOCATION)

    val test = JacksonTest("one", "two")
    val ser = mapper.writeValueAsString(test)
    println(ser)
    val de = mapper.readValue<JacksonTest>(ser)
    println(de)
}

@JvmRecord
data class JacksonTest(
    @JsonProperty("propertyOne")
    val one: String,
    @JsonProperty("propertyTwo")
    val two: String
)

The above runs correctly if

Expected behavior

No response

Versions

Java: GraalVM CE 21.0.2+13.1 (build 21.0.2+13-jvmci-23.1-b30) Kotlin: 1.9.22 Jackson-module-kotlin: 2.16.1 Jackson-databind: 2.16.1 Jackson-bom: 2.16.1

Additional context

Discovered when investigating Spring Boot 3.3.X

k163377 commented 2 months ago

This seems to occur without registering a KotlinModule.

In the case of the code you submitted, the annotation is given as a constructor parameter. At this time, databind seems to ignore this annotation. For example, this problem can be avoided by specifying @field:JsonProperty.

I have submitted an issue to jackson-databind regarding this behavior. I'll see what functionality kotlin-module should provide later. https://github.com/FasterXML/jackson-databind/issues/4513

bmorris591 commented 2 months ago

Just tracking this round the houses - it seems to have ended up as a Kotlin bug https://youtrack.jetbrains.com/issue/KT-67977

cowtowncoder commented 2 months ago

Some other context: Jackson 2.18 will finally get Property Introspection rewrite -- https://github.com/FasterXML/jackson-databind/issues/4515 -- completion of which should make it possible to address some problems that formerly could not, wrt Kotlin introspection. Not sure if it could help here but might well do so.