How to disable kotlinx serialization polymorphic descriminator?
Asked Answered
M

2

9

I'm generating JSON for a number of third-party APIs. Many of them accept a list (JSON array) of different objects, however, none of them will accept the "type": "com.mycom.someclass" automatically generated by kotlinx serialization due to the polymorphic nature of the list.

In my use-case, I only care about serializing out. No deserialization is needed.

Current:

[{"type":"com.mycom.Child1","x":"child1"}, {"type":"com.mycom.Child2","y": 23}]

Needed:

[{"x":"child1"}, {"y": 23}]

How can I disable this automatic behavior?

Meliamelic answered 27/5, 2020 at 22:8 Comment(1)
There's no easy way to do it. See this issueVitreous
U
3

Take a look at Json parametric polymorphic deserialization:

You also can serialize data with such serializer. In that case, either registered or default serializer would be selected for the actual property type in runtime. No class discriminator would be added.

You'll need to impelement JsonParametricSerializer and manually select the serializer. As you don't need to support deserialization, the implementation would be trivial.

Unchancy answered 27/5, 2020 at 23:28 Comment(1)
I take it this approach does not work for nested sealed hierarchies. That is, the JsonParametricSerializer can only be used at the top level of a class hierarchy.Meliamelic
S
0

The trick is to make the polymorphic type distinctive. As an example

sealed class Vehicle {
   data class Car(...)
   data class Bike(...)
}

val v: Vehicle = Vehicle.Car()

// Contains "type" as you serialize Vehicle, which is polymorphic
val json1 = Json.encodeToString(v) 

// Does not contain "type" as you serialize Vehicle.Car, which is distinctive
val json2 = when(v) {
    is Vehicle.Car -> Json.encodeToString(v)
    is Vehicle.Bike -> Json.encodeToString(v)
} 

Same when you'd use this in Ktor:

// Contains "type" as you serialize Vehicle, which is polymorphic
setBody(v) 

// Does not contain "type" as you serialize Vehicle.Car, which is distinctive
val json2 = when(v) {
    is Vehicle.Car -> setBody(v)
    is Vehicle.Bike -> setBody(v)
} 
Scaffold answered 24/9, 2022 at 15:3 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.