Je ne parviens pas à obtenir une liste de types génériques à partir d'une classe personnalisée (tours):
val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)
ça disait:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
Créez ce plaisir en ligne:
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
et alors vous pouvez l'appeler de cette façon:
val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
NOTE : Cette approche n'était pas possible auparavant dans les anciennes versions du plugin Kotlin, mais vous pouvez maintenant l'utiliser.
Alternatives précédentes:
ALTERNATIVE 1:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
Vous devez mettre object :
et le type spécifique dans fromJson<List<Turns>>
ALTERNATIVE 2:
Comme @cypressious mention, cela peut également être réalisé de la manière suivante:
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
utilisé comme:
val turnsType = genericType<List<Turns>>()
Cela résout le problème:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
La première ligne crée un expression d'objet qui descend de TypeToken
et obtient ensuite le Java Type
. _ De celui-ci. Ensuite, le Gson().fromJson
method nécessite le type spécifié pour le résultat de la fonction (qui doit correspondre à la TypeToken
créée). Deux versions de ce travail, comme ci-dessus, ou:
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
Pour faciliter la création de TypeToken
, vous pouvez créer une fonction d'assistance qui doit obligatoirement être inline pour pouvoir utiliser paramètres de type réifiés :
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
Ce qui peut alors être utilisé de l'une des manières suivantes:
val turnsType = genericType<List<Turns>>()
// or
val turnsType: List<Turns> = genericType()
Et l'ensemble du processus peut être encapsulé dans une fonction d'extension pour l'instance Gson
:
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
Pour que vous puissiez simplement appeler Gson et ne pas vous inquiéter pour le TypeToken
:
val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
Ici, Kotlin utilise l'inférence de type d'un côté de l'assignation et des génériques réifiés pour qu'une fonction en ligne passe à travers le type complet (sans effacement), et l'utilise pour construire un TypeToken
et créer le appel à Gson
Une autre option (pas sûr que cela paraisse plus élégant que les autres) pourrait être un appel comme celui-ci:
turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.Java).toMutableList()
Vous utilisez donc le Java Array class one liner au lieu de "pure Kotlin".
val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
object : TypeToken<List<SaleItemResponse>>() {}.type)
C’est ma façon d’analyser un tableau de données dans Kotlin.
Cela fonctionne aussi bien, et est plus simple
inline fun <reified T> Gson.fromJson(json: String) : T =
this.fromJson<T>(json, T::class.Java)
J'ai utilisé quelque chose comme ceci pour convertir T
en string
& String
à T
à l'aide de Gson
. Pas exactement ce que vous cherchez, mais juste au cas où.
Déclaration d'extension
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)
Usage
// 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
}
}