如何在Kotlin的Gson注册InstanceCreator?

Hel*_*oCW 5 java json gson kotlin

我可以使用MutableList<MDetail>Gson正确地使用代码1保存到json字符串,但是当我尝试MutableList<MDetail>使用代码2从json字符串恢复对象时出现错误。我搜索了一些资源,看来我需要注册InstanceCreator。

如何InstanceCreator用Kotlin 写一个注册码?谢谢!

错误

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.
Run Code Online (Sandbox Code Playgroud)

代码1

private var listofMDetail: MutableList<MDetail>?=null
mJson = Gson().toJson(listofMDetail) //Save
Run Code Online (Sandbox Code Playgroud)

代码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)
Run Code Online (Sandbox Code Playgroud)

我的课

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

添加

我使用后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()

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()
Run Code Online (Sandbox Code Playgroud)

s1m*_*nw1 5

Gson很难像您一样反序列化多态对象MutableList<DeviceDef>。这是您需要做的:

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

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

    创建Gson实例:

    val adapter = RuntimeTypeAdapterFactory
            .of(DeviceDef::class.java)
            .registerSubtype(BluetoothDef::class.java)
            .registerSubtype(WiFiDef::class.java)
    
    val gson = GsonBuilder().setPrettyPrinting().registerTypeAdapterFactory(adapter).create()
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在工厂中注册您的每个子类型,它将按预期工作:)