-
Notifications
You must be signed in to change notification settings - Fork 652
Description
Describe the bug
The type
discriminator field vanishes when I wrap the generated serializer with JsonTransformingSerializer
.
I have a business description of operation that shall be performed. This operation is sent to multiple services through different protocols. Each of them requires some "transformation" of the operation. The wrapper determines which service to route the operation to. The wrappers are sometimes classes when no extra business attributes are needed, such as in the case below, where an additional field with version is added.
To Reproduce
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.JsonTransformingSerializer
import kotlinx.serialization.json.jsonObject
@Serializable
sealed interface Operation
@Serializable
data class Insert(val id: Int, val name: String) : Operation
@Serializable
data class Delete(val id: Int) : Operation
@Serializable
sealed interface MessageWrapper
@JvmInline
@Serializable
value class InsertWrapper(val insert: Insert) : MessageWrapper
@JvmInline
@Serializable
value class DeleteWrapper(val delete: Delete) : MessageWrapper
object MessageWrapperSerializer : JsonTransformingSerializer<MessageWrapper>(MessageWrapper.serializer()) {
override fun transformSerialize(element: JsonElement): JsonElement {
return JsonObject(element.jsonObject + ("version" to JsonPrimitive("1.0")))
}
}
fun main() {
val json = Json { ignoreUnknownKeys = true }
val message = InsertWrapper(Insert(1, "one"))
val encoded = json.encodeToString(MessageWrapper.serializer(), message)
println(encoded)
val encoded2 = json.encodeToString(MessageWrapperSerializer, message)
println(encoded2)
}
Prints:
{"type":"Insert","id":1,"name":"one"}
{"id":1,"name":"one","version":"1.0"}
Expected behavior
The type
should be present in the second output too. I would expect it to read:
{"type":"Insert","id":1,"name":"one","version":"1.0"}
The example above works better when the wrapper class is not value class
, but that changes the structure.
{"type":"InsertWrapper","insert":{"id":1,"name":"one"}}
{"type":"InsertWrapper","insert":{"id":1,"name":"one"},"version":"1.0"}
Environment
- Kotlin version: 2.1.20
- Library version: 1.8.1 (both
- Kotlin platforms: JVM
- Gradle version: 8.10.2
- IDE version (if bug is related to the IDE) IntellijIDEA 2025.1.3
- Other relevant context: