首页 > 解决方案 > 用 Moshi 序列化密封类

问题描述

以下将产生 IllegalArgumentException 因为您“无法序列化抽象类”

sealed class Animal {
    data class Dog(val isGoodBoy: Boolean) : Animal()
    data class Cat(val remainingLives: Int) : Animal()
}

private val moshi = Moshi.Builder()
    .build()

@Test
fun test() {
    val animal: Animal = Animal.Dog(true)
    println(moshi.adapter(Animal::class.java).toJson(animal))
}

我曾尝试使用自定义适配器解决此问题,但我能想到的唯一解决方案是为每个子类显式编写所有属性名称。例如:

class AnimalAdapter {
    @ToJson
    fun toJson(jsonWriter: JsonWriter, animal: Animal) {
        jsonWriter.beginObject()
        jsonWriter.name("type")
        when (animal) {
            is Animal.Dog -> jsonWriter.value("dog")
            is Animal.Cat -> jsonWriter.value("cat")
        }

        jsonWriter.name("properties").beginObject()
        when (animal) {
            is Animal.Dog -> jsonWriter.name("isGoodBoy").value(animal.isGoodBoy)
            is Animal.Cat -> jsonWriter.name("remainingLives").value(animal.remainingLives)
        }
        jsonWriter.endObject().endObject()
    }

    ....
}

最终,我希望生成如下所示的 JSON:

{
    "type" : "cat",
    "properties" : {
        "remainingLives" : 6
    }
}
{
    "type" : "dog",
    "properties" : {
        "isGoodBoy" : true
    }
}

我很高兴必须使用自定义适配器来编写每种类型的名称,但我需要一个能够自动序列化每种类型的属性的解决方案,而不必手动编写它们。

标签: androidjsonkotlinmoshi

解决方案


我认为您需要多态适配器来实现这一点,这需要 moshi-adapters 工件。这将启用具有不同属性的密封类的序列化。更多详细信息在本文中: https ://proandroiddev.com/moshi-polymorphic-adapter-is-d25deebbd7c5


推荐阅读