web-dev-qa-db-ja.com

KotlinでGsonでTypeToken +ジェネリックを使用する方法

カスタムクラス(ターン)からジェネリック型のリストを取得できません。

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

と言いました:

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

このインラインの楽しみを作成します。

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)

NOTE:このアプローチは、以前の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>>()
174
Juancho

これにより問題が解決します。

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

最初の行は、TypeTokenから派生する オブジェクト式 を作成し、そこからJava Typeを取得します。次に、Gson().fromJsonメソッドには、関数の結果に指定されたタイプ(TypeTokenに一致する必要があります)が必要です。上記のように、この作業の2つのバージョンまたは:

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

TypeTokenの作成を簡単にするために、ヘルパー関数を作成できます。ヘルパー関数は inline である必要があり、そのため reified type parameters を使用できます。

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へ

25
Jayson Minard

別のオプション(他のオプションよりもエレガントに見えるかどうかはわかりません)は、次のような呼び出しです。

turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.Java).toMutableList()

したがって、「純粋なKotlin」ではなく、Java Arrayクラスの1つのライナーを使用しています。

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

Kotlinでデータ配列を解析する私の方法です。

9
Toàn Mỹ

これも同様に機能し、より簡単です

    inline fun <reified T> Gson.fromJson(json: String) : T = 
         this.fromJson<T>(json, T::class.Java)
4

このようなものを使用して、Tstringに変換し、StringTに戻し、Gsonを使用しました。まさにあなたが探しているものではなく、念のため。

拡張機能の宣言

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
        }
    }
3
harsh_v