web-dev-qa-db-fra.com

Jackson comment transformer JsonNode en ArrayNode sans casting?

Je change ma bibliothèque JSON d'org.json à Jackson et je souhaite migrer le code suivant:

JSONObject datasets = readJSON(new URL(DATASETS));
JSONArray datasetArray =  datasets.getJSONArray("datasets");

Maintenant, à Jackson, j'ai les éléments suivants:

ObjectMapper m = new ObjectMapper();
JsonNode datasets = m.readTree(new URL(DATASETS));      
ArrayNode datasetArray = (ArrayNode)datasets.get("datasets");

Cependant, je n'aime pas le casting là-bas, existe-t-il une possibilité pour un ClassCastException? Existe-t-il une méthode équivalente à getJSONArray dans org.json afin que je puisse gérer correctement les erreurs si ce n'est pas un tableau?

97
Konrad Höffner

Oui, le design de l'analyseur manuel de Jackson est assez différent des autres bibliothèques. En particulier, vous remarquerez que JsonNode possède la plupart des fonctions que vous associeriez généralement aux nœuds de tableau d'autres API. En tant que tel, vous n'avez pas besoin de transtyper vers un ArrayNode à utiliser. Voici un exemple:

JSON:

{
    "objects" : ["One", "Two", "Three"]
}

Code:

final String json = "{\"objects\" : [\"One\", \"Two\", \"Three\"]}";

final JsonNode arrNode = new ObjectMapper().readTree(json).get("objects");
if (arrNode.isArray()) {
    for (final JsonNode objNode : arrNode) {
        System.out.println(objNode);
    }
}

Sortie:

"Un"
"Deux"
"Trois"

Notez l'utilisation de isArray pour vérifier que le nœud est réellement un tableau avant de procéder à une itération. La vérification n'est pas nécessaire si vous avez une confiance absolue dans votre structure de données, mais elle est disponible si vous en avez besoin (et cela ne diffère pas de la plupart des autres bibliothèques JSON).

219
Perception

Existe-t-il une méthode équivalente à getJSONArray dans org.json afin que je puisse gérer correctement les erreurs si ce n'est pas un tableau?

Cela dépend de votre contribution. c'est-à-dire les éléments que vous récupérez à partir de l'URL. Si la valeur de l'attribut "datasets" est un tableau associatif plutôt qu'un tableau simple, vous obtiendrez un ClassCastException.

Mais là encore, l'exactitude de votre ancienne version dépend également de l'entrée. Dans le cas où votre nouvelle version jette un ClassCastException, l'ancienne version lancera JSONException. Référence: http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray (Java.lang.String)

1
Stephen C

Je suppose qu'à la fin de la journée, vous souhaitez utiliser les données de ArrayNode en les itérant. Pour ça:

Iterator<JsonNode> iterator = datasets.withArray("datasets").elements();
while (iterator.hasNext()) 
        System.out.print(iterator.next().toString() + " "); 

ou si vous aimez les flux et les fonctions lambda:

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )
0
Wildhammer