Hello, guys. I'm trying to deserialize such polymo...
# serialization
i
Hello, guys. I'm trying to deserialize such polymorphic json structure using custom KSerializer:
Copy code
{
  "data": {
    "type1": [
      {
        "id": 1,
        "payload": {
          "fieldA": "123",
          "fieldB": "321"
        }
      }
    ],
    "type2": [
      {
        "id": 1,
        "payload": {
          "fieldC": "789",
          "fieldD": "101112"
        }
      }
    ]
  }
}
And I want to get this as result:
Copy code
Map<String, List<Item>>
where key is
type1, type2
and value list item is:
Copy code
data class Item(
    val id: Int,
    val payload: ItemPayload
)
sealed class ItemPayload {
    data class PayloadOne(
        val fieldA: String,
        val fieldB: String
    )

    data class PayloadTwo(
        val fieldC: String
        val fieldD: String
    )
}
Right now I'm thinking about to deserialize the JSON to intermediate data class (which has
JsonObject
instead of
ItemPayload
), then determine which serializer do I need to use on each particular item and then deserialize the
JsonObject
to exact
ItemPayload
based on map key (
type1, type2
) But I don't understand how can I deserialize
JsonObject
inside the
KSerializer
.
j
JsonObject has a keys attribute, then i'm assuming you'd need to have a when (key) { "blah" -> type of setup and then do a get("blah") on that JsonObject to get the sub-JSON which you can then deserialize Sounds messy, maybe there's a better way
pseudo code: obj.keys.forEach { key -> when (key) { "type1" -> result.type1 = JSON.decodeFromJsonElement(Type1.serializer(), obj["type1"]) } }
n
i am not sure if this is stillin the current version of kotlinx.serialization but you can use this Serializer
Copy code
object MessageSerializer: JsonParametricSerializer<YourType>(YourType::class) {
    override fun selectSerializer(element: JsonElement): KSerializer<out YourType> {
        val obj = element.jsonObject
        if(obj.contains("someKey")) {
            return SomeEvent.seriualizer()
        }
        TODO("add more serializers")
    }
}
iirc there was some even better solutions in dev at the time which should be available in 1.0
i
@Nikky thanks. Seems like your way to do that does not fit my requirements, since the type of payload can not be determined in payload deserializer, but in parent deserializers (one for
Map<String, List<Item>
)
@janvladimirmostert thank you! But it seems that I don't have an access to Json instance inside KSerializer. I can't use
JsonConfiguration.Default
because I have own configuration.
n
iirc you can cast the decoder to JsonDecoder or so, not sure if the name is exactly like so
i
@Nikky Nice! Thank you! It's
JsonInput
and it have
Json
instance, awesome! 🙂
n
deserialize the 
JsonObject
 to exact 
ItemPayload
 based on map key (
type1, type2
 )
this would also work if you used
Copy code
@Serializable
data class Data(
  val type1: Item<PayloadOne>
  val type2: Item<PayloadTwo>
)
since it seems like all keys and assosciated types are known, if not you can still make it ignore unknown keys
i
Thank you 🙂