如何在Kotlin中用GSON实现多态列表反序列化?

时间:2018-03-03 19:34:29

标签: android kotlin gson retrofit2 moshi

我有一个数据Feed返回一个列表,该列表可以是三种类型之一(说类型A,B和C)。上面的所有类型共享2个属性,其余属性特定于类型。我尝试使用该模式。

abstract class Parent (val type: String, val id: String)

data class TypeA(override val type: String ... )
data class TypeB(override val type: String ... )

我正在使用Retrofit并尝试将列表反序列化为

List<? extends Parent>
在Kotlin应该

List<out Parent>

然而,GSON在实例化抽象的父类时会抛出反序列化错误。

java.lang.RuntimeException: Failed to invoke public com.XX.Parent() with no args

我是如何在Kotlin中实现这一点的?

2 个答案:

答案 0 :(得分:0)

当您在问题中标记了Moshi时,我将为您提供一种使用MOshi的PolymorphicJsonAdapterFactory进行标记的方法。您基本上可以根据对象属性的值将其解析为不同的类型。

要做的第一件事是将父类型声明为密封类,并从其扩展其他类型:

sealed class Parent(val type: String){
    data class TypeA(override val type: String, ... ): Parent(type) 
    data class TypeB(override val type: String, ... ): Parent(type) 
}

现在您要告诉Moshi如何解析Parent对象。您需要注册PolymorphicJsonAdapterFactory

val moshi = Moshi.Builder()
      .add(PolymorphicJsonAdapterFactory.of(Parent::class.java, "type")
          .withSubtype(TypeA::class.java, "typeA")
          .withSubtype(TypeB::class.java, "typeB")
      .build()

,如果属性“ type”的值为“ typeA”,它将反序列化为TypeA实例。如果属性“ type”为“ typeB”,则TypeB一样明智

您可以在此处查看另一个示例: https://github.com/square/moshi/blob/master/adapters/src/main/java/com/squareup/moshi/adapters/PolymorphicJsonAdapterFactory.java

答案 1 :(得分:-2)

我认为您需要在Kotlin中添加“extends”修饰符(“”)并将参数传递给Parent的构造函数,如下所示:

data class TypeA(override val type: String, val id: String) : Parent(type, id)