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

在Android应用程序中,我需要为具有单一抽象级别的Kotlin数据类反序列化Json数据。 但我没有任何想法,在构造函数中放置正确的属性。

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

abstract class Shape(open val x: Int, open val y: Int) 

有两个派生

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

 data class Square(val width: Int, override val x: Int, override val y: Int): Shape(x, y) 

所以我的目标是,不要实例化一个形状。 所以,总是反序列化它的派生。 后来我需要处理其他类中的一些集合属性,如:

 val shapes: List<Shape> 

但我也必须知道每个元素的派生类型。

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

 val square = gson.fromJson(SQUARE_JSON, Square::class.java) 

我总是得到一个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) 

有没有可能正确地反序列化这个类,而不写一个自定义的Gson TypeAdapter或丢失数据类的优势?

谢谢

ShapeSquare声明字段xySquare实例实际上将xy的值存储两次。 为了避免这种情况,您可以从Shape构造函数中移除xy ,并将它们声明为abstractCircle一样,例如:

 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() 

Gson现在可以成功地对CircleSquare对象进行序列化和反序列化。

你确定这是数据类的Gson问题吗? 它应该与他们正确地工作,只有不可空字段可能是一个问题。

你的错误表明你有同名的字段。
如果您不想包含任何特定字段,则必须使用@Transient对其进行注释

如果你现在还不能将基类转换成Kotlin,那么@Transient注解对我@Transient

 data class Circle(val radius: Int, @Transient val x: Int, @Transient val y: Int): Shape(x, y) data class Square(val width: Int, @Transient val x: Int, @Transient val y: Int): Shape(x, y)