kotlinforandroid
06/02/2022, 8:02 PMkotlinforandroid
06/02/2022, 8:03 PM@Serializable(with = ValueDeserializer::class)
sealed interface Value
@JvmInline
@Serializable
value class NumberValue(val value: Int) : Value
@JvmInline
@Serializable
value class StringValue(val value: String) : Value
object ValueDeserializer :
JsonContentPolymorphicSerializer<Value>(Value::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out Value> {
if (element !is JsonPrimitive) throw RuntimeException("failed to deserialize literal value")
return if (element.jsonPrimitive.isString) StringValue.serializer() else NumberValue.serializer()
}
}
@Test
fun `deserializes from literal value`() {
val inputs = listOf(
("42", NumberValue(42)),
("\"42\"", StringValue("42")),
)
inputs.forEach {
// Check that the class matches.
val decoded = Json.decodeFromString<Value>(it.first)
assertEquals(decoded is it.second::class, true)
}
}
kotlinforandroid
06/02/2022, 8:04 PMSerializer for class 'Value' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
kotlinx.serialization.SerializationException: Serializer for class 'Value' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
Kotlin 1.6.10
Kotlin Serialization 1.3.3
Android Project, Source Compatibility 1.8, Java 11 (Stacktrace mentions java.base@11.0.11)ephemient
06/02/2022, 8:09 PMephemient
06/02/2022, 8:10 PM@Serializable
data class Container(val value: Value)
but currently the serializer lookup for sealed interface
is broken in cases such as yourskotlinforandroid
06/02/2022, 8:11 PMValue
inside of an object, i.e., "42"
wouldn't work, it would have to be {"value":"42"}
ephemient
06/02/2022, 8:13 PMJson.decodeFromString(ValueDeserializer, it)
ephemient
06/02/2022, 8:14 PMkotlinforandroid
06/02/2022, 8:15 PM{"label": "hello-world", "value": <"string" or number>}
. And I tried to model that value type above.kotlinforandroid
06/02/2022, 8:15 PMephemient
06/02/2022, 8:17 PM@Serializable
data class Container(val label: String, val value: Value)
doesn't it? that should workkotlinforandroid
06/02/2022, 8:18 PMephemient
06/02/2022, 8:19 PM