How to use TypeToken + generics with Gson in Kotlin
我无法从自定义类(转)获得通用类型的列表:
1 2 | val turnsType = TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson(pref.turns, turnsType) |
它说:
1 | cannot access '<init>' it is 'public /*package*/' in 'TypeToken' |
创建此内联乐趣:
1 | inline fun <reified T> Gson.fromJson(json: String) = this.fromJson< T >(json, object: TypeToken< T >() {}.type) |
然后您可以通过以下方式调用它:
1 2 3 | val turns = Gson().fromJson<Turns>(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns) |
先前的选择:
替代方案1:
1 2 | val turnsType = object : TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType) |
您必须将>
替代方案2:
正如@cypressious提及的那样,也可以通过以下方式实现:
1 | inline fun <reified T> genericType() = object: TypeToken< T >() {}.type |
用于:
1 | val turnsType = genericType<List<Turns>>() |
这样可以解决问题:
1 2 | val turnsType = object : TypeToken<List<Turns>>() {}.type val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType) |
第一行创建一个对象表达式,该对象表达式从
1 | val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType) |
为了使创建
1 | inline fun <reified T> genericType() = object: TypeToken< T >() {}.type |
然后可以通过以下两种方式之一使用它:
1 2 3 | val turnsType = genericType<List<Turns>>() // or val turnsType: List<Turns> = genericType() |
整个过程可以包装到
1 | inline fun <reified T> Gson.fromJson(json: String) = this.fromJson< T >(json, object: TypeToken< T >() {}.type) |
这样您就可以致电Gson而不用担心
1 2 3 | val turns = Gson().fromJson<Turns>(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns) |
Kotlin在这里使用的是从赋值一侧或另一侧进行类型推断,并对内联函数使用泛型泛型来传递完整类型(不删除),并使用该泛型构造一个
另一个选择(不确定它看起来比其他选择更优雅)可能是这样的调用:
1 | turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.java).toMutableList() |
因此,您使用的是Java Array类的一个内衬而不是" pure Kotlin"。
1 2 | val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt, object : TypeToken<List<SaleItemResponse>>() {}.type) |
这是我在Kotlin中解析数据数组的方式。
我使用类似的方法使用
Declaring extension
1 2 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 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 } } |
这同样有效,并且更简单
1 2 | inline fun <reified T> Gson.fromJson(json: String) : T = this.fromJson< T >(json, T::class.java) |