zt
05/19/2022, 7:50 PM[ { "somekey": { } }, { "someotherkey": { } } ]
I wanna be able to check the name of the first key in the object and then serialize to a specific class depending on what it isLandry Norris
05/19/2022, 8:06 PMLandry Norris
05/19/2022, 8:08 PM[ { "type": "MySubclass", "field1": "value1" }, { "type": "MyOtherClass", "anotherField": "value2" }, { "type": "ClassWithNoFields" } ]
zt
05/19/2022, 8:13 PMephemient
05/20/2022, 8:33 AM@Serializable(with = Foo.Serializer::class)
sealed class Foo {
@Serializable
object Bar : Foo()
@Serializable
object Baz : Foo()
object Serializer : KSerializer<Foo> {
override val descriptor: SerialDescriptor = SerialDescriptor("Foo", Surrogate.serializer().descriptor)
override fun serialize(encoder: Encoder, value: Foo) {
encoder.encodeSerializableValue(
Surrogate.serializer(),
Surrogate(
bar = value as? Bar,
baz = value as? Baz,
)
)
}
override fun deserialize(decoder: Decoder): Foo {
val surrogate = decoder.decodeSerializableValue(Surrogate.serializer())
return surrogate.bar ?: surrogate.baz ?: throw SerializationException("missing key")
}
}
@Serializable
private data class Surrogate(
val bar: Bar? = null,
val baz: Baz? = null,
)
}
Json.decodeFromString<List<Foo>>("""[{"bar":{}},{"baz":{}}]""") == listOf(Foo.Bar, Foo.Baz)
ribesg
05/20/2022, 9:05 AMribesg
05/20/2022, 9:06 AMribesg
05/20/2022, 9:07 AM{ "a": 0, "b": 1 }
and { "b": 1, "a": 0 }
are strictly identicalephemient
05/20/2022, 9:08 AMribesg
05/20/2022, 9:10 AMephemient
05/20/2022, 9:13 AMephemient
05/20/2022, 9:46 AMobject FooJsonSerializer : JsonTransformingSerializer<Foo>(Foo.serializer()) {
private val discriminator = Foo::class.findAnnotation<JsonClassDiscriminator>()?.discriminator ?: "type"
override fun transformSerialize(element: JsonElement): JsonElement = buildJsonObject {
put(element.jsonObject[discriminator]!!.jsonPrimitive.content, JsonObject(element.jsonObject - discriminator))
}
override fun transformDeserialize(element: JsonElement): JsonElement = buildJsonObject {
val (type, value) = element.jsonObject.entries.single()
put(discriminator, type)
for ((key, subvalue) in value.jsonObject) put(key, subvalue)
}
}
(error-checking etc. omitted)