使用“JsonContentPolymorphicSerializer”时,Kotlinx 反序列化不包含抽象类的属性

Iva*_*gor 5 android kotlin kotlinx.serialization

假设有一个抽象类BaseClass ...

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable(with = PolymorphicSerializer::class)
abstract class BaseClass {
    @SerialName("bid")
    var baseId: String? = null
 }
Run Code Online (Sandbox Code Playgroud)

...扩展它的类ExtendedClass ...

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
class ExtendedClass
    (@SerialName("eid")
     var newId: String? = null
) : BaseClass()
Run Code Online (Sandbox Code Playgroud)

...和多态序列化器

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement

object PolymorphicSerializer  : JsonContentPolymorphicSerializer<BaseClass>(BaseClass::class) {
    override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out BaseClass> {
        return ExtendedClass.serializer()
    }
}
Run Code Online (Sandbox Code Playgroud)

使用PolymorphicSerializer是因为 JSON 可以反序列化为基于某些属性扩展BaseClass 的不同类(为了简单起见,我只使用了ExtendedClass.serializer()

现在,如果我们尝试将通用 JSON 反序列化为ExtendedClass ...

class DeserializationTest {
    @Test
    fun deserialization_isCorrect() {
        val extendedClass = Json {
            ignoreUnknownKeys = true
        }.decodeFromString<BaseClass>("""{"bid":"bid","eid":"eid"}""")

        assertEquals("bid", extendedClass.baseId)
    }
}
Run Code Online (Sandbox Code Playgroud)

...测试失败

java.lang.AssertionError: 
Expected :bid
Actual   :null
Run Code Online (Sandbox Code Playgroud)

如果我尝试序列化ExtendClass ...

val extendedClass = ExtendedClass()
extendedClass.baseId = "bid"
extendedClass.newId = "eid"

val encodedJson = Json {
    ignoreUnknownKeys = true
}.encodeToString(extendedClass)
Run Code Online (Sandbox Code Playgroud)

我可以看到encodedJson{"eid":"eid"}但如果我删除JsonContentPolymorphicSerializer这工作正常(用@Serialized替换@Serialized(with = PolymorphicSerializer::class)),encodedJson{"bid":"bid", “开斋节”:“开斋节”}

因此,由于某种原因JsonContentPolymorphicSerializer不考虑超类的属性。

有人知道为什么会这样吗?

Ste*_*ris -1

BaseClass您将通过提供自定义 来覆盖生成的序列化器PolymorphicSerializer

@Serializable(with = PolymorphicSerializer::class)
abstract class BaseClass { ... }
Run Code Online (Sandbox Code Playgroud)

您已有效地删除了 的序列化器BaseClass。(事实上​​,我很惊讶这不会引发某种类型的错误/反序列化失败。)

相反,删除@Serializable,并且在任何需要反序列化不包含类鉴别器的 JSON 的地方,将您的自定义PolymorphicSerializer作为参数传递给decodeFromString

Ps 我还建议以不同的方式命名它。PolymorphicSerializer是 kotlinx.serialization 中的一个实际序列化器,这让我很失望。;)