Andrey Tabakov
05/28/2025, 10:13 AM@Serializable
data class MyConcreteDataClass(val name: String)
@Serializable
data class MyCommonClass(val value: MyConcreteDataClass)
I want to support a new implementation while also maintaining compatibility:
@Serializable
sealed interface AllDataClasses {
val name: String
}
@Serializable
data class MyConcreteDataClass(override val name: String): AllDataClasses
@Serializable
data class MyNewConcreteDataClass(override val name: String): AllDataClasses
@Serializable
data class MyCommonClass(val value: AllDataClasses)
May be there is a way to provide a fallback serializer if legacy object doesn’t point to polymorphic object?Eugen Martynov
05/28/2025, 3:52 PMAndrey Tabakov
05/28/2025, 3:53 PMEugen Martynov
05/28/2025, 3:56 PMtry/catch
and in catch try to deserialise it in the old way. On Android we usually always migrate data on the update if needed. Like if database schema was changed, etc. Maybe you should try to do that?Eugen Martynov
05/28/2025, 3:58 PMAndrey Tabakov
05/28/2025, 3:59 PMBruno Medeiros
06/02/2025, 12:29 AMBruno Medeiros
06/02/2025, 12:34 AMJsonContentPolymorphicSerializer
and checking for the missing discriminator, with he help of @KeepGeneratedSerialiozer
Bruno Medeiros
06/02/2025, 1:54 AMpolymorphicDefaultDeserializer
seems to be a better solution for this.
the following code works for me:
fun main() {
val json = Json {
serializersModule = SerializersModule {
polymorphicDefaultDeserializer(ChildWithPoly::class) { ChildWithPoly.ChildLegacy.serializer() }
}
}
val obj = Parent(ChildWithPoly.ChildLegacy("Hello World!"))
assert(obj == json.decodeFromString<Parent>("""{"child":{"type":"ChildLegacy", "s":"Hello World!"}}"""))
assert(obj == json.decodeFromString<Parent>("""{"child":{"s":"Hello World!"}}"""))
}
@Serializable
data class Parent(
val child: ChildWithPoly,
)
@Serializable
sealed interface ChildWithPoly {
@Serializable
@SerialName("ChildLegacy")
data class ChildLegacy(
val s: String,
): ChildWithPoly
@Serializable
@SerialName("ChildNew")
data class ChildNew(
val s: String,
): ChildWithPoly
}
// previously not part of a hierarchy
@Serializable
data class ChildNoPoly(
val s: String,
)
Andrey Tabakov
06/02/2025, 8:17 AMpolymorphicDefaultDeserializer
, but it won’t work in my case. Your example works. I started investigating the problem and found that polymorphicDefaultDeserializer
does not work with Json { useArrayPolymorphism = true }
. I will create an issue.Bruno Medeiros
06/02/2025, 8:18 AMBruno Medeiros
06/02/2025, 8:20 AMAndrey Tabakov
06/02/2025, 8:22 AM{"child":["ChildLegacy",{"s":"Hello World!"}]} // with array polymorphism
{"child":{"type":"ChildLegacy","s":"Hello World!"}} // without
Andrey Tabakov
06/02/2025, 8:24 AMuseArrayPolymorphism = false
because we already have a lot of files in that (arrayPolymorphism) formatBruno Medeiros
06/02/2025, 8:24 AMBruno Medeiros
06/02/2025, 8:25 AMAndrey Tabakov
06/02/2025, 8:25 AMAndrey Tabakov
06/02/2025, 8:26 AMBruno Medeiros
06/02/2025, 8:26 AMAndrey Tabakov
06/02/2025, 8:27 AMBruno Medeiros
06/02/2025, 8:27 AMBruno Medeiros
06/02/2025, 8:28 AMBruno Medeiros
06/02/2025, 8:29 AMAndrey Tabakov
06/02/2025, 8:30 AM