如何在Kotlin中使用Gson注册InstanceCreator? [英] How to register an InstanceCreator with Gson in Kotlin?

查看:738
本文介绍了如何在Kotlin中使用Gson注册InstanceCreator?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以使用代码1将 MutableList< MDetail> 保存为使用Gson的json字符串,
但是当我尝试恢复 MutableList< MDaeil> 从代码2的json字符串中获得对象。
我搜索了一些资源,似乎我需要注册一个InstanceCreator。



如何使用Kotlin编写一个注册 InstanceCreator 代码?
$ b

错误

 引起通过:java.lang.RuntimeException:无法调用接口model.DeviceDef的无参数构造函数。用Gson注册这个类型的InstanceCreator可以解决这个问题。 

代码1

  private var listofMDetail:MutableList< MDetail>?= null 
mJson = Gson()。toJson(listofMDetail)//保存




代码2

  var mJson:PreferenceTool(this,getString(R.string.SavedJsonName),)
var aMListDetail = Gson()。fromJson< MutableList< MDetail>>(mJson)

内嵌乐趣< reified T> Gson.fromJson(json:String)= this.fromJson< T>(json,object:TypeToken< T>(){} .type)

我的课程

 接口DeviceDef 
$ bDevice
$ b data class MDDeil(val status:Boolean = false):DeviceDef
data class WiFiDef(val name:String,val status:Boolean = false) val_id:Long,val deviceList:MutableList< DeviceDef>)
{
inline fun< reified T> getDevice():T {
return deviceList.filterIsInstance(T :: class.java).first()
}
}
$ b

新增



使用 val myGson = GsonBuilder().setPrettyPrinting()。registerTypeAdapterFactory(adapter).create(),当我使用 open class DeviceDef 时,我可以得到正确的结果,为什么?

  open class DeviceDef 

data class BluetoothDef(val status:Boolean = false):DeviceDef ()
data class WiFiDef(val name:String,val status:Boolean = false):DeviceDef()
$ b $ val adapter = RuntimeTypeAdapterFactory
.of(DeviceDef :: class。 java)
.registerSubtype(BluetoothDef :: class.java)
.registerSubtype(WiFiDef :: class.java)


data class MDetail(val _id:Long ,val deviceList:MutableList< DeviceDef>)
{
inline fun< reified T> getDevice():T {
return deviceList.filterIsInstance(T :: class.java).first()
}
}

val myGson = GsonBuilder() .setPrettyPrinting()。registerTypeAdapterFactory(adapter).create()


解决方案

< Gson正在对 MutableList< DeviceDef> 中的多态对象进行反序列化。以下是您需要做的事:


  1. 添加 RuntimeTypeAdapterFactory.java 对于您的项目手动(似乎不是 gson库的一部分)。另请参阅此答案

  2. 更改您的代码使用工厂

创建 Gson p>

  val adapter = RuntimeTypeAdapterFactory 
.of(DeviceDef :: class.java)
.registerSubtype(BluetoothDef :: class.java)
.registerSubtype(WiFiDef :: class.java)


val gson = GsonBuilder()。setPrettyPrinting()。registerTypeAdapterFactory(adapter).create()




  1. 在工厂注册您的每个子类型,将按预期工作:)


I can use Code 1 to save MutableList<MDetail> to json string using Gson correctly, But I get the error when I try to restore MutableList<MDetail> object from json string with Code 2. I have search some resources, it seems that I need to register an InstanceCreator.

How can I write a register an InstanceCreator code with Kotlin? Thanks!

Error

Caused by: java.lang.RuntimeException: Unable to invoke no-args constructor for interface model.DeviceDef. Registering an InstanceCreator with Gson for this type may fix this problem.

Code 1

private var listofMDetail: MutableList<MDetail>?=null
mJson = Gson().toJson(listofMDetail) //Save

Code 2

var mJson: String by PreferenceTool(this, getString(R.string.SavedJsonName) , "")
var aMListDetail= Gson().fromJson<MutableList<MDetail>>(mJson)

inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)

My Class

interface DeviceDef

data class BluetoothDef(val status:Boolean=false):  DeviceDef
data class WiFiDef(val name:String, val status:Boolean=false) : DeviceDef

data class MDetail(val _id: Long, val deviceList: MutableList<DeviceDef>)
{
    inline fun <reified T> getDevice(): T {
        return deviceList.filterIsInstance(T::class.java).first()
    }
}

Added

After I use val myGson = GsonBuilder().setPrettyPrinting().registerTypeAdapterFactory(adapter).create(), I can get the correct result when I use open class DeviceDef , why?

open class DeviceDef

data class BluetoothDef(val status:Boolean=false):  DeviceDef()
data class WiFiDef(val name:String, val status:Boolean=false) : DeviceDef()

val adapter = RuntimeTypeAdapterFactory
        .of(DeviceDef::class.java)
        .registerSubtype(BluetoothDef::class.java)
        .registerSubtype(WiFiDef::class.java)


data class MDetail(val _id: Long, val deviceList: MutableList<DeviceDef>)
{
    inline fun <reified T> getDevice(): T {
        return deviceList.filterIsInstance(T::class.java).first()
    }
}

val myGson = GsonBuilder().setPrettyPrinting().registerTypeAdapterFactory(adapter).create()

解决方案

Gson is having a hard time deserialising polymorphic objects as in your MutableList<DeviceDef>. Here's what you need to do:

  1. Add the RuntimeTypeAdapterFactory.java as to your project manually (does not seem to be part of gson library). See also this answer.

  2. Change your code to use the factory

Create Gson instance:

val adapter = RuntimeTypeAdapterFactory
        .of(DeviceDef::class.java)
        .registerSubtype(BluetoothDef::class.java)
        .registerSubtype(WiFiDef::class.java)


val gson = GsonBuilder().setPrettyPrinting().registerTypeAdapterFactory(adapter).create()

  1. register each of your subtypes in the factory and it will work as intended :)

这篇关于如何在Kotlin中使用Gson注册InstanceCreator?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆