Android Kotlin - GSON JsonDeserializer 中用于处理 Array 与 Obj 的泛型
Android Kotlin - Generics in GSON JsonDeserializer to handle Array vs Obj
我需要我们的 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.
这是我正在使用的一个数据示例class,供参考:
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)
为了解决这个问题,我不得不为每种类型的对象(可以是数组或对象)制作多个适配器。不幸的是,因为我有大约 50 种不同类型的对象,所以在 GsonBuilder 中调用 "registerTypeAdapters" 有很多重复代码。
为了简化一点,我为 return 一个基于给定 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
方法是行不通的,因为我必须显式发送特定类型。
我需要我们的 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.
这是我正在使用的一个数据示例class,供参考:
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)
为了解决这个问题,我不得不为每种类型的对象(可以是数组或对象)制作多个适配器。不幸的是,因为我有大约 50 种不同类型的对象,所以在 GsonBuilder 中调用 "registerTypeAdapters" 有很多重复代码。
为了简化一点,我为 return 一个基于给定 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
方法是行不通的,因为我必须显式发送特定类型。