如何在 Kotlin 中将 TypeToken + 泛型与 Gson 一起使用
How to use TypeToken + generics with Gson in Kotlin
我无法从自定义 class(转向)中获取通用类型列表:
val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)
它说:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
创造这个内联乐趣:
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)
以前的备选方案:
备选方案 1:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
您必须在 fromJson<List<Turns>>
中输入 object :
和具体类型
备选方案 2:
正如@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
派生的 object expression,然后从中获取 Java Type
。然后 Gson().fromJson
方法需要为函数结果指定的类型(应该与创建的 TypeToken
相匹配)。此作品的两个版本,如上或:
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
为了更容易创建 TypeToken
您可以创建一个辅助函数,它需要 inline so that it can use reified type parameters:
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 数组 class 一个衬里而不是“纯 Kotlin”。
val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
object : TypeToken<List<SaleItemResponse>>() {}.type)
这是我在kotlin中解析数据数组的方式。
我使用类似的方法将 T
转换为 string
并使用 Gson
将 String
转换回 T
。不完全是您要找的东西,但以防万一。
Declaring extension
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)
Usage
// 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
}
我无法从自定义 class(转向)中获取通用类型列表:
val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)
它说:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
创造这个内联乐趣:
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)
以前的备选方案:
备选方案 1:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
您必须在 fromJson<List<Turns>>
object :
和具体类型
备选方案 2:
正如@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
派生的 object expression,然后从中获取 Java Type
。然后 Gson().fromJson
方法需要为函数结果指定的类型(应该与创建的 TypeToken
相匹配)。此作品的两个版本,如上或:
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
为了更容易创建 TypeToken
您可以创建一个辅助函数,它需要 inline so that it can use reified type parameters:
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 数组 class 一个衬里而不是“纯 Kotlin”。
val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
object : TypeToken<List<SaleItemResponse>>() {}.type)
这是我在kotlin中解析数据数组的方式。
我使用类似的方法将 T
转换为 string
并使用 Gson
将 String
转换回 T
。不完全是您要找的东西,但以防万一。
Declaring extension
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)
Usage
// 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
}