Osman Saral
08/28/2023, 3:39 PMJsonContentPolymorphicSerializer
with a collection? 🧵Osman Saral
08/28/2023, 3:39 PM{ "data": ["a", "b"] }
(list of strings)
or
{ "data": [{"foo": 1}, {"foo": 2}] }
(list of object)
So I created a JsonContentPolymorphicSerializer
:
@Serializable
sealed interface Element {
@Serializable
class ObjectValue(val value: MyClass): Element
@JvmInline @Serializable
value class StringValue(val value: String): Element
}
object MySerializer : JsonContentPolymorphicSerializer<Element>(
Element::class
) {
override fun selectDeserializer(element: JsonElement) =
when (element) {
is JsonObject -> Element.ObjectValue.serializer()
else -> Element.StringValue.serializer()
}
}
data class A(
@Serializable(with = /* can't use my serializer here */) //doesn't work
val data: List<Element>
)
glureau
08/28/2023, 3:44 PM@Serializable(with=MySerializer::class) sealed interface Element
instead?glureau
08/28/2023, 3:47 PMOsman Saral
08/28/2023, 6:51 PM@Serializable(with = MySerializer::class)
sealed interface Element
@Serializable
data class MyClass(.....): Element
@JvmInline @Serializable
value class StringValue(val value: String): Element
object MySerializer : JsonContentPolymorphicSerializer<Element>(
Element::class
) {
override fun selectDeserializer(element: JsonElement) =
when (element) {
is JsonObject -> MyClass.serializer()
else -> StringValue.serializer()
}
}
data class A(
val data: List<Element>
)
glureau
08/29/2023, 7:13 AM@Serializable
data class A(
val data: List<Element>,
)
val json = Json {}
@Test
fun foo() {
testSerialization(A(listOf(MyClass("foo"), StringValue("bar"))))
testSerialization(A(listOf(MyClass("foo"), MyClass("bar"))))
testSerialization(A(listOf(StringValue("foo"), StringValue("bar"))))
}
fun testSerialization(a: A) {
val encoded = json.encodeToString(a)
println(encoded)
val decoded = json.decodeFromString<A>(encoded)
println(decoded)
assertEquals(a, decoded)
}
// OUTPUT :
{"data":[{"uuid":"foo"},"bar"]}
A(data=[MyClass(uuid=foo), StringValue(value=bar)])
{"data":[{"uuid":"foo"},{"uuid":"bar"}]}
A(data=[MyClass(uuid=foo), MyClass(uuid=bar)])
{"data":["foo","bar"]}
A(data=[StringValue(value=foo), StringValue(value=bar)])
NB: it allows to mix MyClass & StringValue, is it fine for you?Osman Saral
08/29/2023, 7:24 AMOsman Saral
08/29/2023, 7:29 AMOsman Saral
08/29/2023, 1:10 PMglureau
08/29/2023, 1:40 PMOsman Saral
08/29/2023, 1:51 PM