如何在Kotlin中使用Gson的TypeToken +泛型

我无法从自定义类(Turns)中获取泛型类型的列表:

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

它说:

 cannot access '<init>' it is 'public /*package*/' in 'TypeToken' 

    4 Solutions collect form web for “如何在Kotlin中使用Gson的TypeToken +泛型”

    创建这个内联的乐趣:

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

    然后你可以这样调用它:

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

    注意 :这种方法在旧的kotlin插件版本中是不可能的,但是现在您可以使用它了。


    以前的替代方案:

    备选1:

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

    你必须把object :和来自fromJson<List<Turns>>的具体类型


    备选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的对象表达式 ,然后从中获取Java Type 。 然后Gson().fromJson方法或者需要为函数结果指定的类型(它应该与创建的TypeToken匹配)。 这个工作的两个版本,如上所述或者:

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

    为了方便创建TypeToken ,可以创建一个辅助函数,该函数需要内联才能使用实体类型参数 :

     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<Array<Turns>>(allPurchasesString, Array<Turns>::class.java).toMutableList() 

    所以你正在使用Java Array类的班轮,而不是“纯Kotlin”。

    Kotlin language will be the best programming language for Android.