【问题标题】:Android Kotlin - Generics in GSON JsonDeserializer to handle Array vs ObjAndroid Kotlin - GSON JsonDeserializer 中用于处理 Array 与 Obj 的泛型
【发布时间】:2019-04-24 19:11:19
【问题描述】:

我需要我们的 GSON 解析器来处理数组与单个对象。我已经让它可以识别任何 MutableList 并落入下面的 Deserializer 适配器。但是,在实际将序列化为对象时,我错过了它不喜欢“T”类型的部分。我知道它此时需要该类型,但是鉴于我们这里有什么,我是否缺少能够推断出这一点的东西?

class JsonArrayObjectAdapter<T>: JsonDeserializer<MutableList<T>> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): MutableList<T> {
        val list = mutableListOf<T>()
        json?.let {
            context?.let {
                if (json.isJsonArray) {
                    for (element in json.asJsonArray) {
                        val obj: T = context.deserialize(element, T::class.java) // does not like this
                        list.add(obj)
                    }
                } else if (json.isJsonObject) {
                    val obj: T = context.deserialize(json, T!!::class.java) // does not like this
                    list.add(obj)
                }
            }
        }
        return list
    }
}

尝试使用 T::class.java 时出现此编译错误:

Cannot use 'T' as reified type parameter. Use a class instead.

这是我正在使用的数据类的示例,供参考:

data class ExampleDataClass(
    @SerializedName("ExampleKey") val exampleVar: MutableList<ExampleSubDataClass>
)

这是我如何创建 gson:

val listType = object : TypeToken<MutableList<ExampleDataSubClass>>() {}.getType()
val gson = GsonBuilder()
        .registerTypeAdapter(listType, JsonArrayObjectAdapter<ExampleDataSubClass>())
        .create()
result = gson.fromJson(jsonString, ExampleDataClass::class.java)

【问题讨论】:

    标签: android generics kotlin gson json-deserialization


    【解决方案1】:

    为了解决这个问题,我必须为每种可以是数组或对象的对象类型制作多个适配器。很不幸,因为我有大约 50 种不同类型的这些对象,所以在 GsonBuilder 中调用“registerTypeAdapters”会产生很多重复代码。

    为了简化一点,我做了一个泛型方法来返回一个基于给定 JsonElement 和泛型 T 对象的数组:

    fun <T> getJSONArray(json: JsonElement, type: Type, ctx: 
    JsonDeserializationContext): ArrayList<T> {
        val list = ArrayList<T>()
        if (json.isJsonArray) {
            for (e in json.asJsonArray) {
                list.add(ctx.deserialize<Any>(e, type) as T)
            }
        } else if (json.isJsonObject) {
            list.add(ctx.deserialize<Any>(json, type) as T)
        } else {
            throw RuntimeException("Unexpected JSON type: " + json.javaClass)
        }
        return list
    }
    

    以及使用上述方法定义适配器的示例:

    class JsonArrayObjectAdapterExampleDataClass: JsonDeserializer<ArrayList<ExampleDataClass>> {
        override fun deserialize(json: JsonElement, typeOfT: Type, ctx: JsonDeserializationContext): ArrayList<ExampleDataClass> {
            return getJSONArray(json, ExampleDataClass::class.java, ctx)
        }
    }
    

    简单地将typeOfT var 传递给getJSONArray 方法是行不通的,因为我必须显式发送特定类型。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2016-01-27
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多