繁体   English   中英

如何在 Kotlin 中将 TypeToken + 泛型与 Gson 一起使用

[英]How to use TypeToken + generics with Gson in Kotlin

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

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

它说:

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

创造这个内联乐趣:

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

然后你可以这样调用它:

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

以前的替代品:

备选方案 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)

第一行创建了一个TypeTokenTypeToken对象表达式,然后从中获取 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

另一种选择(不确定它看起来比其他选择更优雅)可能是这样的调用:

turns = Gson().fromJson(stringObject, Array<Turns>::class.java).toMutableList()

因此,您使用的是 java Array 类第一行而不是“纯 Kotlin”。

val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
    object : TypeToken<List<SaleItemResponse>>() {}.type)

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

我使用这样的东西使用GsonT转换为string & StringT 不完全是您正在寻找的,但以防万一。

声明扩展

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> Gson.fromJson(json: String) : T = 
         this.fromJson<T>(json, T::class.java)

将 Gson 反序列化为ArrayList<T> Kotlin generic reified function使用此代码

 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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM