J'ai récemment commencé à jouer avec les chaînes JSON
et on m'a dit que la bibliothèque de Google, Gson
, était la nouvelle façon branchée de gérer ces problèmes.
D'après ce que j'ai compris, une chaîne JSON
est essentiellement une carte. Où chaque variable pointe vers une valeur de la chaîne.
Par exemple:
String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\"}
Jusqu'ici tout va bien. Des informations telles que la date de création de cette chaîne JSON
peuvent être affectées à une variable avec le code suivant:
Gson gson = new Gson();
Map<String, String> map = new HashMap<String, String>();
map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());
String createdAt = map.get("created_at");
C'est presque artistique dans la beauté simple. Mais c'est là que la beauté se termine et que commence ma confusion.
Ce qui suit est une extension de la chaîne JSON
ci-dessus;
String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\",\"user\":{\"id_str\":\"366301747\",\"name\":\"somethingClever\",\"screen_name\":\"somethingCoolAndClever\"}}";
Ma question est de savoir comment ces "crochets entre crochets" fonctionnent pour la section user
de la JSON
?
Comment pourrais-je affecter les valeurs spécifiées dans ces parenthèses aux variables?
Quelqu'un peut-il m'expliquer, ou me montrer dans le code, comment Gson
gère ce genre de choses et comment je peux les utiliser?
En bref, pourquoi ...
String jsonInput = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\",\"user\":{\"id_str\":\"366301747\",\"name\":\"somethingClever\",\"screen_name\":\"somethingCoolAndClever\"}}";
Gson gson = new Gson();
Map<String, String> map = new HashMap<String, String>();
map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());
String name = map.get("name");
System.out.println(name);
... imprimer null
?
Oubliez Java. Vous devez d’abord comprendre le format JSON . C'est fondamentalement ça
object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null
Votre deuxième JSON String
(qui a un "
manquant) est le suivant (utilisez jsonlint.com pour formater)
{
"created_at": "Sat Feb 08 15:37:37 +0000 2014",
"id": "432176397474623489",
"user": {
"id_str": "366301747",
"name": "somethingClever",
"screen_name": "somethingCoolAndClever"
}
}
Le JSON est un objet, {}
extérieur, qui contient trois paires, created_at
qui est une chaîne JSON, id
qui est également une chaîne JSON et user
qui est un objet JSON. Cet objet JSON contient trois autres paires, qui sont toutes des chaînes JSON.
Tu as demandé
Comment attribuer les valeurs spécifiées entre ces crochets aux variables ?
La plupart des bibliothèques d'analyse/génération JSON avancées sont conçues pour convertir JSON en Pojos et inversement.
Vous pouvez donc mapper votre format JSON sur les classes Java.
class Pojo {
@SerializedName("created_at")
private String createdAt;
private String id;
private User user;
}
class User {
@SerializedName("id_str")
private String idStr;
private String name;
@SerializedName("screen_name")
private String screenName;
}
// with appropriate getters, setters, and a toString() method
Notez le @SerializedName
pour que vous puissiez continuer à utiliser les conventions de dénomination Java pour vos champs.
Vous pouvez maintenant désérialiser votre JSON
Gson gson = new Gson();
Pojo pojo = gson.fromJson(jsonInput2, Pojo.class);
System.out.println(pojo);
serait imprimer
Pojo [createdAt=Sat Feb 08 15:37:37 +0000 2014, id=432176397474623489", user=User [idStr=366301747, name=somethingClever, screenName=somethingCoolAndClever]]
montrant que tous les champs ont été définis correctement.
Quelqu'un peut-il m'expliquer ou me montrer, dans le code, comment Gson gère ce genre de choses et comment je peux les utiliser?
Le code source de Gson est disponible gratuitement. Tu peux le trouver en ligne. C'est complexe et une explication de code source ne conviendrait pas ici. En termes simples, il utilise l'objet Class
que vous fournissez pour déterminer comment il mappera les paires JSON. Il examine les champs de la classe correspondante. Si ces champs sont d’autres classes, il se reproduit jusqu’à ce qu’il ait construit une carte de tout ce dont il a besoin pour être désérialisé.
En bref, pourquoi est-ce que ... affiche null?
Parce que votre objet JSON racine n'a pas de paire nommée name
. Au lieu d'utiliser Map
, utilisez le type JsonObject
de Gson.
JsonObject jsonObject = new Gson().fromJson(jsonInput2, JsonObject.class);
String name = jsonObject.get("user") // get the 'user' JsonElement
.getAsJsonObject() // get it as a JsonObject
.get("name") // get the nested 'name' JsonElement
.getAsString(); // get it as a String
System.out.println(name);
qui imprime
somethingClever
La classe de méthode ci-dessus aurait pu générer un certain nombre d'exceptions si elles n'étaient pas du type approprié. Si, par exemple, nous avions fait
String name = jsonObject.get("user") // get the 'user' JsonElement
.getAsJsonArray() // get it as a JsonArray
cela échouerait car user
n'est pas un tableau JSON. Plus précisément, il jetterait
Exception in thread "main" Java.lang.IllegalStateException: This is not a JSON Array.
at com.google.gson.JsonElement.getAsJsonArray(JsonElement.Java:106)
at com.spring.Example.main(Example.Java:19)
Ainsi, la classe JsonElement
(qui est la classe parente de JsonObject
, JsonArray
et quelques autres) fournit des méthodes pour vérifier ce que c'est. Voir le javadoc.
La chaîne JSON a la structure suivante:
{
created_at: "",
id: "",
user: {
id_str: "",
name: "",
screen_name: ""
}
}
Lorsque vous mettez les valeurs dans la carte en utilisant le code:
Map<String, Object> map = new HashMap<String, Object>();
map = (Map<String, Object>) gson.fromJson(jsonInput, map.getClass());
Il a les valeurs clés suivantes:
created_at
id
user
et c’est pourquoi vous pouvez utiliser map.get("created_at")
.
Maintenant, puisque vous voulez obtenir le nom de l'utilisateur, vous devez obtenir la carte de l'utilisateur:
LinkedTreeMap<String, Object> userMap = (LinkedTreeMap<String, Object>) map.get("user");
Dans la userMap
, vous obtiendrez les valeurs de clé suivantes:
id_str
name
screen_name
Maintenant, vous pouvez obtenir la name
de la user
String name = userMap.get("name");
Pour les personnes qui viennent ici à la recherche d'un moyen de convertir LinkedTreeMap en objet:
MyClass object = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) theLinkedTreeMapObject)), MyClass .class)
Cela m'a été utile lorsque j'ai eu besoin d'analyser un objet générique tel que:
Class fullObject {
private String name;
private String objectType;
private Object objectFull;
}
Mais je ne sais pas quel objet le serveur allait envoyer. L'objetFull deviendra un LinkedTreeMap
user
est une JsonObject
elle-même:
JsonObject user = map.get("user");
D'accord. Tout d'abord, JSON est l'abréviation de "JavaScript Object Notation". Votre affirmation selon laquelle "une chaîne JSON est essentiellement une carte" est incorrecte. Un bloc JSON est un graphe d'objet, décrit à l'aide de la syntaxe du langage JavaScript. Étant donné que vous essayez de contraindre un graphe d'objet à une paire de valeurs Sting kay, il ne fonctionnera que dans les cas où un graphe d'objet JSON donné est essentiellement ce qu'il est (donc pas très souvent). Une stratégie plus efficace serait probablement gson.fromJson()
qui convertira votre JSON en un graphe d'objet Java approprié.