Generics 如何使用TypeToken+;Kotlin中带有Gson的泛型

Generics 如何使用TypeToken+;Kotlin中带有Gson的泛型,generics,gson,kotlin,typetoken,Generics,Gson,Kotlin,Typetoken,我无法从自定义类中获取泛型类型列表(次): val-turnsType=TypeToken(){}.type val turns=Gson().fromJson(pref.turns,turnsType) 它说: cannot access '<init>' it is 'public /*package*/' in 'TypeToken' 无法访问“”它是“TypeToken”中的“public/*package*/” 创建此内联乐趣: inline fun <reifi

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

val-turnsType=TypeToken(){}.type
val turns=Gson().fromJson(pref.turns,turnsType)
它说:

cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
无法访问“”它是“TypeToken”中的“public/*package*/”

创建此内联乐趣:

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

val turnsType = genericType<List<Turns>>()
val turnsType=genericType()

这解决了问题:

val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
为了更容易创建
TypeToken
,您可以创建一个helper函数,该函数是必需的,以便它可以使用:

这样您就可以直接调用Gson,而不必担心
TypeToken

val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
val turns=Gson().fromJson(pref.turns)
//或
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)
inline fun Gson.fromJson(json:String):T=
this.fromJson(json,T::class.java)
另一个选项(不确定它是否比其他选项更优雅)可能是这样的调用:

turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.java).toMutableList()
turns=Gson()
因此,您使用的是java数组类one liner,而不是“纯Kotlin”。

val obj:MutableList=Gson(),
对象:TypeToken(){}.type)

这是我在kotlin解析数据数组的方法。

我使用类似的方法将
T
转换为
string
string
返回到
T
,使用
Gson
。不完全是你想要的,只是以防万一

声明扩展名


Gson的Kotlin
通用具体化函数
反序列化为
ArrayList
使用此代码

 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
}
内联乐趣获取(…):ArrayList{
val str=“[{},{}]”
val type=TypeToken.getParameterized(ArrayList::class.java,T::class.java)
val t=Gson().fromJson(str,type)
返回t
}

您还可以为自己创建一个帮助器方法:
inline-fun-genericType()=object:TypeToken(){}.type
甚至扩展Gson,使其具有新的fromJson重载。Kotlin是为了扩展而设计的,所以扩展Gson可以使它更漂亮并隐藏TypeToken。我建议进行编辑,使答案更完整和正式,因为许多使用Gson的人可能会看到这个答案。我在答案中添加了解释,并链接到Kotlin参考文献中用于解决问题的主题。。。因此,人们不必阅读所有其他的答案或评论。如果您接受编辑,我可以删除下面的我的答案。编辑被拒绝,请参阅下面的我的答案,以获得将所有答案和评论合并为一个连贯答案的完整版本。您接受了自己的答案,但答案不完整。删除kotlin警告:inline fun genericType():Type?=对象:TypeToken(){}.typeHi@Jayson,我无法让它在Android Studio中如此有趣地运行。似乎还可以,但当我执行
Gson()时,它没有被识别。fromJson(pref.turns)
@juancho您能告诉我“未识别”是什么意思吗?编译器错误?你已经从上面导入了扩展方法并可用了吗?我在Android Studio中复制并粘贴了你的代码,并在我的kotlin类中导入了乐趣。我试着按照你说的做,但出于某种原因,编译器告诉我这种乐趣是不存在的。我已经在使用其他扩展函数,但我不知道你的建议有什么不起作用。您使用的是哪个版本的AS和Kotlin?请再试一次。这与Android studio没有直接关系,Kotlin在里面或外面都是一样的。您是在创建
Gson()
的实例,还是像创建静态实例一样创建
Gson
?您需要第一个实例。返回类型必须为Null。否则,Gson库中的Java代码可以返回null,但Kotlin假定该类型不可为null。因此,您可以在Kotlin获得NPE。由于TypeToken不能在每部手机上可靠工作,因此这是我的最佳解决方案。一个简单的一行纯科特林。这应该是公认的答案,简短而简单。
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
val turnsType = genericType<List<Turns>>()
// or
val turnsType: List<Turns> = genericType()
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)
    inline fun <reified T> Gson.fromJson(json: String) : T = 
         this.fromJson<T>(json, T::class.java)
turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.java).toMutableList()
val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
    object : TypeToken<List<SaleItemResponse>>() {}.type)
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)
// 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
        }
    }
 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
}