when looking at sealed interfaces (polymoprhism) i...
# serialization
b
when looking at sealed interfaces (polymoprhism) is there a way to tell the deserializer that an object with property "something" needs to deserialize to A, otherwise to B?
✅ 1
c
Which formats are you interested in? I don't think there's a format-agnostic way to do this
b
json
you could probably always go for a custom serializer
JsonTypeInfo(use = DEDUCTION)
c
For JSON, you can write a custom deserializer that deserializes into a
JsonObject
and then use whatever code you want to convert it into the final object
➕ 1
b
I see, so no deduction equivalent available, thank you!
c
This is using the BSON format but it's basically the same idea with JSON: gitlab.com/opensavvy/ktmongo/-/blob/…/Geo.kt?ref_type=heads#…
c
For simple cases the JSON
classDiscriminator
lets you use a property other than
type
to distinguish between the types https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#class-discriminator-for-polymorphism
b
There's also the JsonContentPolymorphicSerializer, which lets you pick a serializer based on the json (similar to Ivan's suggestion, but most of the boilerplate is taken care of for you)
👀 1
🙌 1
j
@Bernhard
@GhostSerialization(inferred = true)
does field-presence polymorphism (like Jackson
DEDUCTION
). You can use it only on that sealed hierarchy — dual-annotate, put the Ghost converter before KotlinX so Ghost handles that DTO and everything else falls through — without replacing the rest of the stack, and those models tend to decode faster too. github.com/juanchurtado1991/ghost-serializer
Copy code
@Serializable // keep for KotlinX call sites
@GhostSerialization(inferred = true)
sealed class SmartEvent {
    @Serializable
    @GhostSerialization
    data class Temperature(@GhostSignature val celsius: Double) : SmartEvent()

    @Serializable
    @GhostSerialization
    data class Motion(@GhostSignature val sensorId: String, val zone: Int) : SmartEvent()
}
// { "celsius": 24.5 } → Temperature
// { "sensorId": "SN-01", "zone": 1 } → Motion

// Ktor — Ghost first, KotlinX fallback
install(ContentNegotiation) {
    ghost()
    json(Json { ignoreUnknownKeys = true })
}
b
thank you