如何在 Kotlin 中结合 Kotlinx 序列化正确使用类继承

xet*_*a11 8 kotlin kotlinx.serialization

我有一个简单的层次结构,包含以下内容:

  • 抽象类 BaseItem
  • 开放类项目:BaseItem
  • 类别 背包 : 物品

它们都应该与 Kotlinx 序列化一起使用。一切都很顺利,直到我添加了Backpack课程。我使用1.4.32Kotlinx 序列化版本。

这是我的类层次结构的详细信息

// Items.kt

@Serializable
sealed class BaseItem {
    abstract val id: String
    abstract val type: ItemType
    abstract var brand: String
    abstract var model: String
    abstract var imageLink: String
    abstract var traits: MutableList<Trait>
    abstract var implicitTraits: MutableList<Trait>
    abstract var details: MutableMap<String, String>
}

@Serializable
open class Item(
    override val id: String = UUID.randomUUID().toString(),
    override val type: ItemType = ItemType.UNDEFINED,
    override var brand: String,
    override var model: String,
    override var imageLink: String,
    override var traits: MutableList<Trait>,
    override var implicitTraits: MutableList<Trait>,
    override var details: MutableMap<String, String>,
) : BaseItem()

@Serializable // is marked as incorrect 
class Backpack(
    brand: String,
    model: String,
    imageLink: String,
    traits: MutableList<Trait>,
    implicitTraits: MutableList<Trait>,
    details: MutableMap<String, String>,
    var volume: Int
) : Item(
    type = ItemType.BACKPACK,
    brand = brand,
    model = model,
    imageLink = imageLink,
    traits = traits,
    implicitTraits = implicitTraits,
    details = details
)
Run Code Online (Sandbox Code Playgroud)

IDE 向我显示以下关于@Serialization附加到 Backpack类的注释的消息。

This class is not serializable automatically because it has primary constructor parameters that are not properties
Run Code Online (Sandbox Code Playgroud)

我无法找出正确的工作方式是什么

Big*_*989 6

这是因为构造函数的参数没有定义为类的属性。要将参数定义为属性,您必须将val或添加var到参数中。这将解决您当前遇到的错误消息:

@Serializable
class Backpack(
    override var brand: String,
    override var model: String,
    override var imageLink: String,
    override var traits: MutableList<Trait>,
    override var implicitTraits: MutableList<Trait>,
    override var details: MutableMap<String, String>,
    var volume: Int
) : Item(
    type = ItemType.BACKPACK,
    brand = brand,
    model = model,
    imageLink = imageLink,
    traits = traits,
    implicitTraits = implicitTraits,
    details = details
)
Run Code Online (Sandbox Code Playgroud)

但这仍然无法编译,因为您最终会得到Serializable class has duplicate serial name of property 'brand', either in the class itself or its supertypes两个类中使用的所有属性。但无论如何,我对这个设计有点惊讶,因为从非抽象类继承通常不是一个好的做法。在不知道意图的情况下,我想知道这样是否也对您不起作用:

sealed class BaseItem {
    abstract val id: String
    abstract val type: ItemType
    abstract var brand: String
    abstract var model: String
    abstract var imageLink: String
    abstract var traits: MutableList<Trait>
    abstract var implicitTraits: MutableList<Trait>
    abstract var details: MutableMap<String, String>
}

@Serializable
data class Item(
    override val id: String = UUID.randomUUID().toString(),
    override val type: ItemType = ItemType.UNDEFINED,
    override var brand: String,
    override var model: String,
    override var imageLink: String,
    override var traits: MutableList<Trait>,
    override var implicitTraits: MutableList<Trait>,
    override var details: MutableMap<String, String>,
) : BaseItem()

@Serializable
data class Backpack(
    override val id: String = UUID.randomUUID().toString(),
    override val type: ItemType = ItemType.BACKPACK,
    override var brand: String,
    override var model: String,
    override var imageLink: String,
    override var traits: MutableList<Trait>,
    override var implicitTraits: MutableList<Trait>,
    override var details: MutableMap<String, String>,
    override var var volume: Int
) : BaseItem()
Run Code Online (Sandbox Code Playgroud)

顺便说一句。删除了@Serializablefrom ,BaseItem因为它是不必要的,因为该类无论如何都是抽象的,因此根本不会被序列化。我还制作了您的课程,data class因为我的印象是这些课程基本上是为了保存数据而存在的,并且通常是用data class. 我留下了很多var我看到的东西,因为我不知道这些的原因,但我这边的一个小提示是你应该更喜欢val尤其var是在data class. 在这种情况下, Avar对我来说感觉像是一种代码味道,您可能需要考虑使用它val。关于此类事情的一个很好的文献是 Kotlin 页面本身:https ://kotlinlang.org/docs/coding-conventions.html#idiomatic-use-of-language-features