如何在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”。