Skip to content

Can't serialize Kotlin Value class that has map inside #873

@kkocel

Description

@kkocel

Search before asking

  • I searched in the issues and found nothing similar.
  • I have confirmed that the same problem is not reproduced if I exclude the KotlinModule.
  • I searched in the issues of databind and other modules used and found nothing similar.
  • I have confirmed that the problem does not reproduce in Java and only occurs when using Kotlin and KotlinModule.

Describe the bug

I tried to serialize Kotlin value class, and failed with:

Cannot invoke "com.fasterxml.jackson.databind.JsonSerializer.serialize(Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)" because "keySerializer" is null (through reference chain: com.paramount.snapshooter.pitstop.SerializationValueClassTest$TimestampedPerson["person"]->java.util.LinkedHashMap["id"])
com.fasterxml.jackson.databind.JsonMappingException: Cannot invoke "com.fasterxml.jackson.databind.JsonSerializer.serialize(Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)" because "keySerializer" is null (through reference chain: com.paramount.snapshooter.pitstop.SerializationValueClassTest$TimestampedPerson["person"]->java.util.LinkedHashMap["id"])

To Reproduce

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.jupiter.api.Test

class SerializationValueClassTest() {

    @Test
    fun `should serialize value class`() {

        val person = Person(
            mapOf(
                "id" to "123",
                "updated" to "2023-11-22 12:11:23",
                "login" to "2024-01-15",
            ),
        )

        val serialized2 = jacksonObjectMapper().writeValueAsString(
            TimestampedPerson(
                123L,
                Person(person.properties),
            )
        )

        val deserialized2 = jacksonObjectMapper().readValue<TimestampedPerson>(serialized2)

        assert(
            deserialized2 == TimestampedPerson(
                123L,
                Person(person.properties),
            )
        )
    }

    @JvmInline
    value class Person(
        val properties: Map<String, Any>,
    )

    data class TimestampedPerson(
        val timestamp: Long,
        val person: Person,
    )
}

Expected behavior

Value class shoud be serialized

Versions

Kotlin: 2.10
Jackson-module-kotlin: 2.17.1
Jackson-databind: 2.18.1

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions