java - 使 Gson 为外部字段确定的接口(interface)类型工作

标签 java android kotlin gson deserialization

问题类似于 this 但不同之处在于 type不包含在反序列化的 JSON 对象中,而是包含在外层(根)中。

像这样:

{
    "type": "A",
    "myObject" : { <- type is NOT stored in here
        ...
    }
}

目的是将此 JSON 对象映射到 Blah

// Code is in Kotlin

interface Foo {
    ...
}

class Bar : Foo { // Map to this if 'type' is A
    ...
}

class Baz : Foo { // Map to this if 'type' is B
    ...
}

class Blah {

    val type : String? = null
    val myObject : Foo? = null
}

我如何制作 myObject映射到 Bar如果typeABaz如果typeB

暂时,我求助于手动读取根 JSON 对象。任何帮助将非常感激。谢谢。

编辑:

尝试将根 JSON 对象映射到 Blah 时使用 Gson fromJson方法,我得到这个错误:Unable to invoke no-args constructor for class Foo . - 但无论如何这是不正确的,因为我需要 myObject专门映射到 BazBar .

最佳答案

这与您提到的问题非常相似。

您可以为 Blah 定义反序列化器并决定应该使用哪个类。

代码如下所示。

import com.google.gson.*

interface Foo {
    fun bark()
}

class Bar : Foo { // Map to this if 'type' is A
    override fun bark() {
        print("bar")
    }
}

class Baz : Foo { // Map to this if 'type' is B
    override fun bark() {
        print("baz")
    }
}

class Blah(val type : String? = null, val myObject : Foo? = null) {
    companion object {
        const val TYPE_A = "A"
        const val TYPE_B = "B"
    }
}

class BlahJsonDeserializer: JsonDeserializer<Blah> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Blah {
        val root = json?.asJsonObject
        val type = root?.get("type")?.asString
        var obj: Foo? = null
        when(type ?: "") {
            Blah.TYPE_A -> { obj = Bar() }
            Blah.TYPE_B -> { obj = Baz() }
        }
        val blah = Blah(type, obj)
        return blah
    }
}

val json = "{'type': 'A', 'myObject': {}}"

val gsonBuilder = GsonBuilder()
gsonBuilder.registerTypeAdapter(Blah::class.java, BlahJsonDeserializer())
val gson = gsonBuilder.create()
val item = gson.fromJson<Blah>(json, Blah::class.java)

item.myObject?.bark() // bar

关于java - 使 Gson 为外部字段确定的接口(interface)类型工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54281035/

相关文章:

java - Android从一个Integer arraylist中获取值变成一个数字

android - HDPI和MDPI问题

kotlin - 什么时候应该更喜欢 Kotlin 扩展函数?

java - 选定的 Activity 模板需要现有的应用程序主题

java - 将来自特定包的消息记录到文件中

android - 如何在 Android AsyncTask 中显示 Toast?

android - 删除数据库后 ContentProvider 未调用 onCreate

reactjs - Ktor 后端的 CORS 问题

class - 如果参数编译时不是实际类型,则kotlin的javaclass.isPrimitive失败

java - Android 的 Facebook 教程应用程序不起作用