generics gson kotlin typetoken

generics - Cómo usar los genéricos TypeToken+con Gson en Kotlin



(6)

Crea esta diversión en línea:

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

y luego puedes llamarlo de esta manera:

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

NOTA : Este enfoque no era posible antes en las versiones antiguas del complemento kotlin, pero ahora puede usarlo.

Alternativas anteriores:

ALTERNATIVA 1:

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

Tienes que poner object : y el tipo específico en fromJson<List<Turns>>

ALTERNATIVA 2:

Como @cypressious menciona, también se puede lograr de esta manera:

inline fun <reified T> genericType() = object: TypeToken<T>() {}.type

usar como:

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

No puedo obtener una Lista de tipos genéricos de una clase personalizada (Turnos):

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

decía:

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


Esto resuelve el problema:

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

La primera línea crea una expresión de objeto que desciende de TypeToken y luego obtiene el Type Java de eso. Luego, el método Gson().fromJson necesita el tipo especificado para el resultado de la función (que debe coincidir con el TypeToken creado). Dos versiones de este trabajo, como arriba o:

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

Para facilitar la creación de TypeToken , puede crear una función auxiliar, que debe estar en inline para que pueda usar parámetros de tipo reified :

inline fun <reified T> genericType() = object: TypeToken<T>() {}.type

Que luego se puede utilizar de cualquiera de estas formas:

val turnsType = genericType<List<Turns>>() // or val turnsType: List<Turns> = genericType()

Y todo el proceso se puede incluir en una función de extensión para la instancia de Gson :

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

Para que pueda llamar a Gson y no preocuparse por el TypeToken :

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

Aquí Kotlin está usando la inferencia de tipos de un lado de la tarea u otro, y ha modificado genéricos para que una función en línea pase a través del tipo completo (sin borrado), y la usa para construir un TypeToken y también hacer la llamada a Gson


Esto también funciona y es más simple

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


Otra opción (no estoy seguro de que se vea más elegante que las otras) podría ser una llamada como esta:

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

Entonces está utilizando el java Array class one liner en lugar de "pure Kotlin".


Utilicé algo como esto para convertir T a string y String nuevo a T usando Gson . No es exactamente lo que está buscando, pero por las dudas.

Declarando extensión

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)

Uso

// 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 } }


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

Es mi manera de analizar la matriz de datos en kotlin.