2017-04-23 114 views
3

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

举一个简单的版本,比方说我有一个形状:

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或松动数据类优势?

谢谢

回答

1

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

您的错误表明您的字段中有相同的名称。
如果有您不希望包括你有@Transient

5

两个ShapeSquare注释任何特定字段声明字段xySquare的一个实例实际上存储了两次xy的值。为了避免这种情况,您可以从Shape构造函数中删除xy,并声明它们为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() 

GSON现在将能够成功地序列化和反序列化CircleSquare对象。

+1

谢谢。这是我正在寻找的解决方案。 – elcolto

1

如果您目前还无法将基类转换为Kotlin,则@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)