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?

madhead
  • 31,729
  • 16
  • 153
  • 201
Newbie
  • 7,031
  • 9
  • 60
  • 85
  • 1
    There's no easy way to do it. See [this issue](https://github.com/Kotlin/kotlinx.serialization/issues/464) – Nicolas May 27 '20 at 23:42

2 Answers2

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.

madhead
  • 31,729
  • 16
  • 153
  • 201
  • 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. – Newbie May 28 '20 at 01:21
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)
} 
crysxd
  • 3,177
  • 20
  • 32