如何在Kotlin中使用Gson注册InstanceCreator? [英] How to register an InstanceCreator with Gson in Kotlin?
问题描述
我可以使用代码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)
我的课程
$ b接口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()
}
}
新增
使用
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>
中的多态对象进行反序列化。以下是您需要做的事:
添加 RuntimeTypeAdapterFactory.java 对于您的项目手动(似乎不是 gson库的一部分)。另请参阅此答案。
- 更改您的代码使用工厂
创建
Gson
p>
val adapter = RuntimeTypeAdapterFactory
.of(DeviceDef :: class.java)
.registerSubtype(BluetoothDef :: class.java)
.registerSubtype(WiFiDef :: class.java)
val gson = GsonBuilder()。setPrettyPrinting()。registerTypeAdapterFactory(adapter).create()
- 在工厂注册您的每个子类型,将按预期工作:)
I can use Code 1 to save
MutableList<MDetail>
to json string using Gson correctly, But I get the error when I try to restoreMutableList<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 useopen 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:
Add the RuntimeTypeAdapterFactory.java as to your project manually (does not seem to be part of gson library). See also this answer.
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()
- register each of your subtypes in the factory and it will work as intended :)
这篇关于如何在Kotlin中使用Gson注册InstanceCreator?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!