laissez Gson lancer des exceptions sur les mauvais types
- Je utiliser Gson à l'intérieur de mes projets pour désérialiser JSON-Chaînes de caractères en Java-Objets. Si je fais une demande, j'attends de bien définir la réponse du Serveur. Le Serveur renvoie le bien-défini la réponse que j'attends, OU il sera de retour moi une (également défini) Objet error.
À mettre les choses au clair: supposons que j'ai un Objet simple comme ceci:
class Dummy{
private String foo;
private int bar;
}
et un Objet d'Erreur comme ceci:
class ErrorHolder{
private RequestError error;
}
class RequestError{
private String publicMsg;
private String msg;
}
Si je reçois un Serveur-réponse, comme
{"foo":"Hello World", "bar":3 }
tout fonctionne comme prévu.
Mais si la réponse est comme ça
{"error":{"publicMsg":"Something bad happened", msg:"you forgot requesting some parameter"}}
Je vais obtenir une sorte de Dummy
objet où foo
est null
et bar
est à 0! Le Gson documentation (fromJson) stipule clairement que:
jette
JsonSyntaxException - si json n'est pas une représentation valable pour une
objet de type classOfT
donc je m'attendais à obtenir une JsonSyntaxException si j'essaie d'analyser la deuxième réponse comme ceci:
Dummy dummy = Gson.fromJson(secondResponse, Dummy.class);
parce que le Json ne représente pas un objet fictif, mais un ErrorHolder Objet.
Donc ma question est: Est-il un moyen, qui Gson détecte un mauvais type en quelque sorte, et me jette une Exception?
Gson est explicitement conçu pour tourner une chaîne JSON en type, pas dynamiquement deviner de quel type que vous voulez dire. La structure de l'objet que vous utilisez doit refléter les données que vous attendez pour analyser, donc si
error
est un domaine que vous pourriez recevoir, il devrait être un champ de la classe.Est-il une alternative parser json, ce qui lui donne intégré dans la facilité?
Regarder la mise à jour de la accepté de Répondre. Le AnnonatedSerializer devrait faire le travail, plus vous avez un contrôle précis sur les champs où ce comportement prend place
OriginalL'auteur Rafael T | 2013-01-09
Vous devez vous connecter pour publier un commentaire.
Malheureusement, la documentation est un peu trompeur.
Il ne fera que jeter de l'exception, si votre classe avait un champ dont le type ne correspond pas à ce qui est dans le JSON, et même alors, il fait des choses folles pour essayer de le réparer (la conversion d'un
int
dans le JSON pour unString
dans votre classe par exemple). Si vous aviez quelque chose comme unDate
champ dans votre POJO et il a rencontré uneint
dans le JSON, il faudrait le jeter. Les champs qui sont présents dans le JSON, mais pas dans votre POJO sont ignorées silencieusement, les champs sont manquants dans le JSON, mais qui existent dans votre POJO sont mis ànull
.À l'heure actuelle, GSON ne pas fournir un mécanisme pour toute sorte de "stricte" de la désérialisation où vous auriez quelque chose comme un
@Required
annotation pour les champs dans votre POJO.Dans votre cas ... je serais tout simplement élargir mon POJO pour inclure une erreur interne de l'objet ... quelque chose comme:
Votre autre option est d'écrire une coutume deserializer qui lève l'exception si le JSON est l'erreur comme:
Modifier pour Ajouter: Quelqu'un upvoted récemment et re-lisant je me suis dit "Hein, vous savez, vous pourriez le faire vous-même et il pourrait être à portée de main".
Voici une ré-utilisable deserializer et d'annotation qui va faire exactement ce que l'OP voulait. La limitation est que si le POJO nécessaire personnalisé deserializer, vous auriez à aller un peu plus loin et passer dans un
Gson
objet dans le constructeur pour désérialiser à l'objet lui-même ou déplacer l'annotation de vérifier dans une méthode distincte et à utiliser dans votre deserializer. Vous pouvez également améliorer la gestion des exceptions en créant votre propre exception et de le passer à laJsonParseException
de sorte qu'il peut être détecté par l'getCause()
en l'appelant.Que tout est dit, dans la grande majorité des cas, cela fonctionne:
De sortie:
OriginalL'auteur
J'ai créé une version mise à jour de Brian la solution qui gère les objets imbriqués et a un couple de d'autres changements mineurs. Le code comprend également une simplification de l'outil de création d' Gson les objets qui sont au courant de classes avec des champs annotés avec JsonRequired.
Et la Réflexion de l'utilitaire de
Si vous utilisez Guice vous pouvez ajouter quelque chose comme ceci à votre module d'injecter Gson objets
OriginalL'auteur
Je ne suis pas fan de la solution retenue. Cela fonctionne, mais ce n'est pas la façon d'utiliser Gson. Gson cartes un particulier JSON schema pour un objet et vice-versa. Idéalement, le JSON que vous utilisez est bien formé (donc si vous avez le contrôle sur le format JSON, envisager de le changer), mais si pas, vous devez concevoir l'analyse de l'objet à manipuler tous les cas, vous vous attendez à recevoir.
Parfois, vous avez besoin d'écrire une coutume
JsonDeserializer
, mais ce n'est pas un de ces moments. Envoyer un message ou d'erreur est très courante, et avec la bonne structure de données GSON peut traiter un cas simple d'utilisation directement.Si vous avez le contrôle sur le JSON schema
Envisager quelque chose comme ceci à la place:
Avis, vous pouvez définir un propre classe wrapper qui fournit
Dummy
objets quand c'est possible:Si vous avez à faire avec le JSON schema
Si vous ne pouvez pas restructurer le schéma, vous devez restructurer l'analyse de classe, il devrait ressembler à quelque chose comme ceci:
C'est moins souhaitable que de fixer le schéma, mais vous obtenez le même général de l'API soit - appel
hasError()
pour voir si la requête a réussi, puis d'appelergetDummy()
ougetError()
en tant que de besoin. Les appels vers l'autre méthode (par exemple,getDummy()
lorsque vous avez reçu une erreur) fail-fast.Si vous n'avez pas la capacité de prédire la structure du JSON que vous essayez de l'analyser, je ne sais pas qu'il y ait beaucoup d'espoir pour vous.
J'ai fini Pas à l'aide de GSon, parser le Json moi-même et en jetant les erreurs le cas échéant
Yep, c'est probablement le meilleur que vous pouvez faire.
OriginalL'auteur