FasterXML / FasterXML/jackson-module-kotlin
Serialization and Deserialization of Kotlin `data class` fails on PolymorphicTypeValidator with Any
- Dominant language
- Kotlin
- Stars
- 1.2k
- Forks
- 187
- Avg merge
- 9h 48m
- Merged PRs (30d)
- 16
Description
### Search before asking
- [X] I searched in the [issues](https://github.com/FasterXML/jackson-databind/issues) and found nothing similar.
### Describe the bug
When trying to deserialize class that contains kotlin value class, Jackson throws `InvalidTypeIdException` with `missing type id property '@class'` on `ObjectMapper.DefaultTyping.NON_FINAL`
Despite adding `@JsonCreator` annotation, I got the same result.
And trying to serialize above class with `ObjectMapper.DefaultTyping.NON_FINAL`, Jackson throws `JsonMappingException` with `class ServerName cannot be cast to class java.lang.String (ServerName is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap') (through reference chain: TestDto["serverName"])`
I'm using PolymorphicTypeValidator and Any class to do serialization and deserialization in Redis. But no matter what settings and annotations I use, the serialization and deserialization fails.
### Version Information
JVM 21
Kotlin 1.8
jackson-core:2.17.2
jackson-databind:2.17.2
jackson-annotations:2.17.2
jackson-datatype-jsr310:2.17.2
jackson-module-kotlin:2.17.2
### Reproduction
```kotlin
@JvmInline
value class ServerName(
val value: String,
) {
companion object {
@JsonCreator
@JvmStatic
fun fromValue(value: String): ServerName {
return ServerName(value)
}
}
}
data class TestDto(
val id: Int,
val serverName: ServerName
)
val objectMapper = ObjectMapper()
.registerKotlinModule()
.registerModule(JavaTimeModule())
.activateDefaultTyping(
BasicPolymorphicTypeValidator.builder().allowIfBaseType(Any::class.java).build(),
ObjectMapper.DefaultTyping.NON_FINAL, // or EVERYTHING
JsonTypeInfo.As.PROPERTY,
)
// on NON_FINAL
fun main() {
val serverName = ServerName("TEST")
val testDto = TestDto(1, serverName)
val serialized = objectMapper.writeValueAsBytes(testDto)
println(String(serialized))
// Expected output: {"id":1,"serverName":"TEST"}
// Actual output: {"id":1,"serverName":{"value":"TEST"}}
val deserialized = objectMapper.readValue(serialized, Any::class.java) // Because of RedisSerializer
println(deserialized)
// Expected output: TestDto(id=1, serverName=ServerName(value=TEST))
// Actual output: Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
}
// on EVERYTHING
fun main() {
val serverName = ServerName("TEST")
val testDto = TestDto(1, serverName)
val serialized = objectMapper.writeValueAsBytes(testDto)
println(String(serialized))
// Expected output: {"id":1,"serverName":"TEST"}
// Actual output: {"id":1,"serverName":{"value":"TEST"}}
val deserialized = objectMapper.readValue(serialized, Any::class.java) // Because of RedisSerializer
println(deserialized)
// Expected output: TestDto(id=1, serverName=ServerName(value=TEST))
// Actual output: Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: class ServerName cannot be cast to class java.lang.String (ServerName is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap') (through reference chain: TestDto["serverName"])
}
```
### Expected behavior
_No response_
### Additional context
_No response_
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.