如何使用Gson反序列化继承的Kotlin数据类

elc*_*lto 8 inheritance json gson kotlin data-class

在Android应用程序中,我需要使用单个抽象级别对Kotlin数据类的Json数据进行反序列化.但我不知道在构造函数中放置正确的属性.

作为一个简单的版本,让我说我有一个形状:

abstract class Shape(open val x: Int, open val y: Int)
Run Code Online (Sandbox Code Playgroud)

有两个推导

data class Circle(val radius: Int, override val x: Int, override val y: Int): Shape(x, y)
Run Code Online (Sandbox Code Playgroud)

data class Square(val width: Int, override val x: Int, override val y: Int): Shape(x, y)
Run Code Online (Sandbox Code Playgroud)

所以我的目标是,不要实例化一个Shape.因此,请始终反序列化其派生.后来我需要在其他类中处理一些集合属性,例如:

val shapes: List<Shape>
Run Code Online (Sandbox Code Playgroud)

但我还必须知道每个元素的派生类型.

当我尝试用Gson反序列化给定的例子时

val square = gson.fromJson(SQUARE_JSON, Square::class.java)
Run Code Online (Sandbox Code Playgroud)

我总是得到一个IllegalArgumentException

java.lang.IllegalArgumentException: class com.example.shapes.model.Square declares multiple JSON fields named x

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.Gson.fromJson(Gson.java:886)
at com.google.gson.Gson.fromJson(Gson.java:852)
at com.google.gson.Gson.fromJson(Gson.java:801)
at com.google.gson.Gson.fromJson(Gson.java:773)
Run Code Online (Sandbox Code Playgroud)

是否有可能在不编写自定义Gson TypeAdapter或丢失数据类优势的情况下正确反序列化此类?

谢谢

mfu*_*n26 9

双方ShapeSquare声明字段xy.Square实际存储值的实例xy两次.为了避免这种情况,你可以删除x,并yShape构造,并把他们定义为abstract.这同样适用于Circle例如:

abstract class Shape {
    abstract val x: Int
    abstract val y: Int
}

data class Circle(val radius: Int, override val x: Int, override val y: Int) : Shape()

data class Square(val width: Int, override val x: Int, override val y: Int) : Shape()
Run Code Online (Sandbox Code Playgroud)

Gson现在能够成功地序列化和反序列化CircleSquare对象.


Joh*_*ohn 1

你确定这是Gson数据类的问题吗?它应该正确地使用它们,只有不可为空的字段可能是问题。

您的错误表明您中有同名的字段。
如果您不想包含任何特定字段,则必须用@Transient