Je souhaite transférer un objet liste via Google Gson, mais je ne sais pas comment désérialiser des types génériques.
Ce que j'ai essayé après avoir regardé cela (réponse de BalusC):
MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass());
mais alors j'obtiens une erreur dans l'éclipse disant "Le type nouveau List () {} doit implémenter la méthode abstraite héritée ..." et si j'utilise une solution rapide, j'obtiens un monstre de plus de 20 stubs de méthode.
Je suis presque sûr qu'il existe une solution plus simple, mais il me semble impossible de la trouver!
Éditer:
Maintenant j'ai
Type listType = new TypeToken<List<MyClass>>()
{
}.getType();
MyClass mc = new Gson().fromJson(result, listType);
Cependant, j'obtiens l'exception suivante sur la ligne "fromJson":
java.lang.NullPointerException
at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47)
at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83)
at java.lang.StringBuilder.append(StringBuilder.java:203)
at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:56)
at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88)
at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:106)
at com.google.gson.JsonDeserializationContextDefault.fromJsonArray(JsonDeserializationContextDefault.java:64)
at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:49)
at com.google.gson.Gson.fromJson(Gson.java:568)
at com.google.gson.Gson.fromJson(Gson.java:515)
at com.google.gson.Gson.fromJson(Gson.java:484)
at com.google.gson.Gson.fromJson(Gson.java:434)
Je fais JsonParseExceptions de capture et « résultat » est non nul.
J'ai vérifié listType avec le débogueur et j'ai obtenu ce qui suit:
- type de liste
- args = ListOfTypes
- list = null
- olvedTypes = Type [1]
- loader = PathClassLoader
- ownerType0 = null
- ownerTypeRes = null
- rawType = Classe (java.util.ArrayList)
- rawTypeName = "java.util.ArrayList"
- args = ListOfTypes
il semble donc que l'invocation "getClass" ne fonctionne pas correctement. Aucune suggestion...?
Edit2: I'v vérifié sur le Guide de l'utilisateur Gson . Il mentionne une exception d'exécution qui devrait se produire lors de l'analyse d'un type générique vers Json. Je l'ai fait "mal" (non illustré ci-dessus), comme dans l'exemple, mais je n'ai pas du tout obtenu cette exception. J'ai donc changé la sérialisation comme dans le guide d'utilisation suggéré. Mais ça n'a pas aidé.
Edit3: Résolu, voir ma réponse ci-dessous.
TokenType
. Avez-vous essayé de cette façon?Réponses:
Méthode pour désérialiser la collection générique:
Étant donné que plusieurs personnes dans les commentaires l'ont mentionné, voici une explication de la façon dont la
TypeToken
classe est utilisée. La constructionnew TypeToken<...>() {}.getType()
capture un type au moment de la compilation (entre le<
et>
) dans unjava.lang.reflect.Type
objet d' exécution . Contrairement à unClass
objet, qui ne peut représenter qu'un type brut (effacé), l'Type
objet peut représenter n'importe quel type en langage Java, y compris une instanciation paramétrée d'un type générique.La
TypeToken
classe elle-même n'a pas de constructeur public, car vous n'êtes pas censé le construire directement. Au lieu de cela, vous construisez toujours une sous-classe anonyme (d'où le{}
, qui est une partie nécessaire de cette expression).En raison de l'effacement des types, la
TypeToken
classe ne peut capturer que les types entièrement connus au moment de la compilation. (Autrement dit, vous ne pouvez pas fairenew TypeToken<List<T>>() {}.getType()
pour un paramètre de typeT
.)Pour plus d'informations, consultez la documentation de la
TypeToken
classe .la source
{ "myObjectArray":[ {....} , {....} , {....} ] }
, j'ai créé le fichier modèle{....}
, comment puis-je obtenir ce code de collection générique pour ne pas supposer que mon élément racine est un tableau sans créer un nouveau fichier objet imbriquéUne autre façon consiste à utiliser un tableau comme type, par exemple:
De cette façon, vous évitez tous les tracas avec l'objet Type, et si vous avez vraiment besoin d'une liste, vous pouvez toujours convertir le tableau en liste en:
À mon humble avis, c'est beaucoup plus lisible.
Et pour en faire une liste réelle (qui peut être modifiée, voir les limitations de
Arrays.asList()
), procédez comme suit:la source
MyClass
valeur et elle sera définie dynamiquement!T[] yourClassList = gson.fromJson(message, T[].class);
// ne peut pas sélectionner la variable de typemcList
dans cette réponse n'était que le résultat de l'appel àArrays.asList
. Cette méthode renvoie une liste sur laquelle la plupart des méthodes facultatives, sinon toutes, ne sont pas implémentées et lèvent des exceptions. Par exemple, vous ne pouvez ajouter aucun élément à cette liste. Comme le suggère la dernière modification, ilArrays.asList
a ses limites et son encapsulation dans un réelArrayList
vous permet d'obtenir une liste plus utile dans de nombreux cas.Array.newInstance(clazz, 0).getClass()
comme décrit dans la réponse de David Wood .Référez-vous à ce post. Type Java générique comme argument pour GSON
J'ai une meilleure solution pour cela. Voici la classe wrapper pour list afin que le wrapper puisse stocker exactement le type de liste.
Et puis, le code peut être simple:
la source
mEntity.rulePattern
?Depuis
Gson 2.8
, nous pouvons créer une fonction util commeExemple utilisant
la source
TypeToken#getParameterized
semble mieux que le hack avec une sousWep, une autre façon d'obtenir le même résultat. Nous l'utilisons pour sa lisibilité.
Au lieu de faire cette phrase difficile à lire:
Créez une classe vide qui étend une liste de votre objet:
Et utilisez-le pour analyser le JSON:
la source
Pour Kotlin, simplement:
ou, voici une fonction utile:
Ensuite, pour utiliser:
la source
inline fun <reified T> buildType() = object : TypeToken<T>() {}.type!!
et appelez-la avec le type List:buildType<List<YourMagicObject>>()
buildType
et appelez-vous également la fonction avec le type générique? Est-ce une faute de frappe? - Cela créerait ArrayList <ArrayList <YourMagicObject>>Exemple:
la source
DevNG
réponse ci-dessus, écrite 2 ans plus tôt: stackoverflow.com/a/17300003/1339923 (et lisez cette réponse pour les mises en garde à cette approche)Comme il répond à ma question d'origine, j'ai accepté la réponse du doc_180, mais si quelqu'un rencontre à nouveau ce problème, je répondrai également à la 2e moitié de ma question:
Le NullPointerError que j'ai décrit n'avait rien à voir avec la liste elle-même, mais avec son contenu!
La classe "MyClass" n'avait pas de constructeur "no args", et ni l'un ni l'autre n'avait sa superclasse. Une fois que j'ai ajouté un simple constructeur "MyClass ()" à MyClass et à sa superclasse, tout a bien fonctionné, y compris la sérialisation et la désérialisation de liste comme suggéré par doc_180.
la source
Voici une solution qui fonctionne avec un type défini dynamiquement. L'astuce consiste à créer le type de tableau approprié à l'aide de Array.newInstance ().
la source
class.cast()
d'éviter l'avertissement incontrôlé provoqué par la conversion vers(T)
. Ou, mieux encore, ne vous embêtez pas avec laArrays.asList()
conversion et utilisez quelque chose comme pour convertir d'un tableau en aList<T>
. De plus, pas besoin de passer une longueur àArray.newInstance()
- un tableau de taille zéro sera assez bon pour faire appelgetClass()
.Je veux ajouter pour une possibilité de plus. Si vous ne souhaitez pas utiliser TypeToken et que vous souhaitez convertir un tableau d'objets json en ArrayList, vous pouvez procéder comme suit:
Si votre structure json est comme:
}
et votre structure de classe est comme:
alors vous pouvez l'analyser comme:
Vous pouvez maintenant accéder à chaque élément de l'objet className.
la source
Reportez-vous à l'exemple 2 pour la compréhension de la classe «Type» de Gson.
Exemple 1: dans ce deserilizeResturant, nous avons utilisé le tableau Employee [] et obtenu les détails
Exemple 2:
la source
J'ai aimé la réponse de kays1 mais je n'ai pas pu l'implémenter. J'ai donc construit ma propre version en utilisant son concept.
Usage:
la source
Dans mon cas, la réponse de @ uncaught_exceptions n'a pas fonctionné, j'ai dû utiliser à la
List.class
place dejava.lang.reflect.Type
:la source