如何在Kotlin中使用Gson的TypeToken +generics
我无法从自定义类(Turns)中获取genericstypes的列表:
val turnsType = TypeToken<List>() {}.type val turns = Gson().fromJson(pref.turns, turnsType)
它说:
cannot access '' it is 'public /*package*/' in 'TypeToken'
创建这个内联的乐趣:
inline fun Gson.fromJson(json: String) = this.fromJson(json, object: TypeToken () {}.type)
然后你可以这样调用它:
val turns = Gson().fromJson(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns)
注意 :这种方法在旧的kotlin插件版本中是不可能的,但是现在您可以使用它了。
以前的替代方案:
备选1:
val turnsType = object : TypeToken>() {}.type val turns = Gson().fromJson>(pref.turns, turnsType)
你必须把object :
和来自fromJson
的具体types >
备选2:
正如@cypressious提到的那样,也可以这样来实现:
inline fun genericType() = object: TypeToken() {}.type
用于:
val turnsType = genericType>()
这解决了这个问题:
val turnsType = object : TypeToken>() {}.type val turns = Gson().fromJson>(pref.turns, turnsType)
第一行创建一个从TypeToken
的对象expression式 ,然后从中获取Java Type
。 然后Gson().fromJson
方法或者需要为函数结果指定的types(它应该与创建的TypeToken
匹配)。 这个工作的两个版本,如上所述或者:
val turns: List = Gson().fromJson(pref.turns, turnsType)
为了方便创建TypeToken
,可以创建一个辅助函数,该函数需要内联才能使用实体types参数 :
inline fun genericType() = object: TypeToken() {}.type
然后可以用以下任何一种方式使用:
val turnsType = genericType>() // or val turnsType: List = genericType()
整个过程可以被包装成一个Gson
实例的扩展函数:
inline fun Gson.fromJson(json: String) = this.fromJson(json, object: TypeToken () {}.type)
所以你可以直接调用Gson而不用担心TypeToken
:
val turns = Gson().fromJson(pref.turns) // or val turns: Turns = Gson().fromJson(pref.turns)
这里Kotlin使用types推断从赋值的一边或另一边,为内联函数的泛化generics通过完整types(没有擦除),并使用它来构造一个TypeToken
并调用Gson
这也适用,而且更简单
inline fun Gson.fromJson(json: String) : T = this.fromJson(json, T::class.java)
另一种选择(不知道它看起来比其他人更优雅)可能是这样的一个电话:
turns = Gson().fromJson>(allPurchasesString, Array::class.java).toMutableList()
所以你正在使用Java Array类的class轮,而不是“纯Kotlin”。