如何在 Kotlin 使用 TypeToken + 泛型

我无法从自定义类中获得泛型类型的 List (转向) :

val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)

它表示:

cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
66474 次浏览

创造这种内嵌的乐趣:

inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object: TypeToken<T>() {}.type)

然后你可以这样称呼它:

val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)

往年选择:

选择一:

val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)

你必须把 object :和特定的类型在 fromJson<List<Turns>>


选择二:

正如@cypressious 提到的,也可以通过这种方式实现:

inline fun <reified T> genericType() = object: TypeToken<T>() {}.type

用作:

val turnsType = genericType<List<Turns>>()

这就解决了问题:

val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)

第一行创建一个从 TypeToken继承下来的 对象表达式,然后从中获取 JavaType。然后,Gson().fromJson方法需要为函数结果指定的类型(该类型应该与创建的 TypeToken匹配)。本作品的两个版本,如上所述或:

val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)

为了更容易地创建 TypeToken,您可以创建一个 helper 函数,它必须是 内嵌式,这样它才能使用 具体化的类型参数:

inline fun <reified T> genericType() = object: TypeToken<T>() {}.type

然后可以用以下两种方式中的任何一种:

val turnsType = genericType<List<Turns>>()
// or
val turnsType: List<Turns> = genericType()

整个过程可以包装成 Gson实例的扩展函数:

inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)

这样你就可以打电话给 Gson,根本不用担心 TypeToken:

val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)

在这里,Kotlin 使用赋值的一边或另一边的类型推断,以及内联函数的具体化泛型来传递完整类型(没有删除) ,并使用它来构造 TypeToken,同时调用 Gson

这种方法同样有效,而且更简单

    inline fun <reified T> Gson.fromJson(json: String) : T =
this.fromJson<T>(json, T::class.java)

另一个选择(不确定它看起来是否比其他选择更优雅)可能是这样的调用:

turns = Gson().fromJson(stringObject, Array<Turns>::class.java).toMutableList()

所以您使用的是 java Array 类 one 而不是“纯 Kotlin”。

val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
object : TypeToken<List<SaleItemResponse>>() {}.type)

这是我在 Kotlin 解析数据阵列的方法。

我使用类似的东西来转换 TstringString回到 T使用 Gson。虽然不是你想要的,但以防万一。

宣布延期

inline fun <reified T : Any> T.json(): String = Gson().toJson(this, T::class.java)
inline fun <reified T : Any> String.fromJson(): T = Gson().fromJson(this,T::class.java)

用法

// Passing an object to new Fragment
companion object {
private const val ARG_SHOP = "arg-shop"


@JvmStatic
fun newInstance(shop: Shop) =
ShopInfoFragment().apply {
arguments = Bundle().apply {
putString(ARG_SHOP, shop.json())
}
}
}


// Parsing the passed argument
private lateinit var shop: Shop


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
shop = it.getString(ARG_SHOP).fromJson() ?: return
}
}

Gson 的 Kotlin generic reified function反序列化为 ArrayList<T>使用这段代码

 inline fun <reified T> get( ... ): ArrayList<T>{
    

val str = "[{},{}]"
    

val type = TypeToken.getParameterized(ArrayList::class.java, T::class.java).type
    

val t = Gson().fromJson<ArrayList<T>>(str, type)
    



return t
}