Correctly determine the type of serializable property

when supertype of serializable class is generic and also serializable,
and contains the property with type with its generic parameter.

Fixes https://github.com/Kotlin/kotlinx.serialization/issues/1264
#KT-43910 Fixed
#KT-49660 Fixed
This commit is contained in:
Leonid Startsev
2022-10-04 20:08:13 +02:00
committed by Space Team
parent 2ea0cdf46d
commit 2a626b27d3
5 changed files with 169 additions and 16 deletions
@@ -0,0 +1,56 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
abstract class Top<T: Any> {
var top: T? = null
}
@Serializable
open class Intermediate<V>: Top<List<V>>() {
var inter: V? = null
override fun toString(): String {
return "Intermediate($top, $inter)"
}
}
@Serializable
open class Bottom: Intermediate<String>() {
var bot: String? = null
override fun toString(): String {
return "Bottom($top, $inter, $bot)"
}
}
@Serializable
class Bottom2: Bottom() {
override fun toString(): String {
return "Bottom2($top, $inter, $bot)"
}
}
@Serializable
data class Full(
val b: Bottom2,
val i: Intermediate<String>
)
fun box(): String {
val j = Json { ignoreUnknownKeys = true }
val b = Bottom2().apply {
top = listOf("a", "b")
inter = "v"
bot = "bot"
}
val f = Full(b, b)
val encoded = j.encodeToString(f)
if (encoded != """{"b":{"top":["a","b"],"inter":"v","bot":"bot"},"i":{"top":["a","b"],"inter":"v"}}""") return "Encoded: $encoded"
val decoded = j.decodeFromString<Full>(encoded)
if (decoded.toString() != "Full(b=Bottom2([a, b], v, bot), i=Intermediate([a, b], v))") return "Decoded: $decoded"
return "OK"
}
@@ -0,0 +1,46 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
import kotlinx.serialization.*
import kotlinx.serialization.json.*
// From #1264
@Serializable
sealed class TypedSealedClass<T>(val a: T) {
@Serializable
class Child(val y: Int) : TypedSealedClass<String>("10") {
override fun toString(): String = "Child($a, $y)"
}
}
// From #KT-43910
@Serializable
open class ValidatableValue<T : Any, V: Any>(
var value: T? = null,
var error: V? = null,
)
@Serializable
class Email<T: Any> : ValidatableValue<String, T>() { // Note this is a different T
override fun toString(): String {
return "Email($value, $error)"
}
}
fun box(): String {
val encodedChild = """{"a":"11","y":42}"""
val decodedChild = Json.decodeFromString<TypedSealedClass.Child>(encodedChild)
if (decodedChild.toString() != "Child(11, 42)") return "DecodedChild: $decodedChild"
Json.encodeToString(decodedChild)?.let { if (it != encodedChild) return "EncodedChild: $it" }
val email = Email<Int>().apply {
value = "foo"
error = 1
}
val encodedEmail = Json.encodeToString(email)
if (encodedEmail != """{"value":"foo","error":1}""") return "EncodedEmail: $encodedEmail"
val decodedEmail = Json.decodeFromString<Email<Int>>(encodedEmail)
if (decodedEmail.toString() != "Email(foo, 1)") return "DecodedEmail: $decodedEmail"
return "OK"
}