本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
简单的记录。
我们在使用gson时,常常需要使用TypeToken解析泛型嵌套的数据,然后将重复代码提取成函数。
实体类:
class Entity<T> {
var type: Int = 0
var data: T? = null
}
将typeToken中的泛型提出:
fun <T> convertJson(json: String): T? {
return try {
val typeToken =
object: TypeToken<Entity<T>>(){}.type
Gson().fromJson<Entity<T>>(json, typeToken).data
} catch (e: java.lang.Exception) {
null
}
}
但实际运行解析报错:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to XXX
原因是在TypeToken使用泛型时,泛型需要是确定的类型。改为使用TypeToken.getParameterized()函数获取type对象。
fun <T> convertJson(json: String, t: Class<T>): T? {
return try {
val typeToken =
TypeToken.getParameterized(Entity::class.java, t).type
Gson().fromJson<Entity<T>>(json, typeToken).data
} catch (e: java.lang.Exception) {
null
}
}
使用TypeToken.getParameterized()可解决gson解析异常的问题。函数需要多传一个参数,T的class对象。
这时我们可以使用reified关键字对函数进行精简:
inline fun <reified T> convertJson(json: String): T? {
return try {
val typeToken =
TypeToken.getParameterized(Entity::class.java, T::class.java).type
Gson().fromJson<Entity<T>>(json, typeToken).data
} catch (e: java.lang.Exception) {
null
}
}
其中reified关键字和inline关键字都是不能省略的,省略reified,AndroidStudio提示:
Cannot use 'T' as reified type parameter. Use a class instead.
省略inline,提示:
Only type parameters of inline functions can be reified.
因为是内联函数,函数体不宜过长,逻辑不易太复杂。
不当之处欢迎指正。