web-dev-qa-db-fra.com

Interroger un objet JSON en Java

Je me demandais s'il existait quelque part une librairie Java capable d'interroger un objet JSON. Plus en profondeur, je cherche quelque chose comme:

String json = "{ data: { data2 : { value : 'hello'}}}";

...
// Somehow we managed to convert json to jsonObject
...

String result = jsonObject.getAsString("data.data2.value");

System.out.println(result);

Je m'attends à obtenir "bonjour" en sortie.

A présent, le moyen le plus rapide que j'ai trouvé est d'utiliser Gson:

jsonObject.getAsJsonObject("data").getAsJsonObject().get("data2").getAsJsonObject("value").getAsString();

Ce n'est pas vraiment facile à écrire et à lire. Y a-t-il quelque chose de plus rapide?

31
Pamput

Je viens de trouver de manière inattendue un projet très intéressant: JSON Path

JsonPath représente JSON ce que XPATH représente XML, un moyen simple d'extraire des parties d'un document donné.

Avec cette bibliothèque, vous pouvez faire ce que vous demandez encore plus facilement, alors ma suggestion précédente:

String hello = JsonPath.read(json, "$.data.data2.value");

System.out.println(hello); //prints hello

J'espère que cela pourrait être utile non plus.

37
n1ckolas

Bien que ce ne soit pas exactement pareil, Jackson a une représentation de Tree Model similaire à Gson:

JsonNode root = objectMapper.readTree(jsonInput);
return root.get("data").get("data2").get("value").asText();

vous devez donc le parcourir étape par étape.

EDIT (août 2015)

Il existe actuellement (depuis Jackson 2.3) un support pour JSON Pointer expressions avec Jackson. Vous pouvez donc utiliser alternativement:

return root.at("/data/data2/value").asText();
19
StaxMan

Tout d'abord, je recommanderais d'envisager la liaison d'objet JSON.

Mais au cas où vous auriez des objets JSON arbitraires et que vous souhaiteriez les traiter de la manière que vous avez décrite, je suggérerais de combiner processeur JSON de Jackson avec ceux de Apache Commons Beanutils .

L'idée est la suivante: Jackson traite par défaut toutes les instances JSON en tant qu'instances Java.util.Map, tandis que Commons Beanutils simplifie l'accès aux propriétés pour les objets, y compris les tableaux et les supports Map.

Donc, vous pouvez l'utiliser comme ceci:

//actually it is a Map instance with maps-fields within
Object jsonObj = objectMapper.readValue(json, Object.class);

Object hello = PropertyUtils.getProperty(jsonObj, "data.data2.value")

System.out.println(hello); //prints hello
16
n1ckolas

Je pense pas moyen.

Considérons une classe Java

class Student {
    Subject subject = new Subject();
}

class Subject {
    String name;
}

Ici, si nous voulons accéder au nom du sujet, alors 

Student stud = new Student();
stud.subject.name; 

Nous ne pouvons pas accéder directement au nom. Si c'est le cas, nous n'obtiendrons pas un nom de sujet correct. Comme ici: 

jsonObject.getAsJsonObject("data")
          .getAsJsonObject()
          .get("data2")
          .getAsJsonObject("value")
          .getAsString();

Si vous souhaitez utiliser le même objet Java, utilisez 

ClassName classObject = new Gson().fromJson(JsonString, ClassName.class);

ClassName doit avoir tous les champs pour correspondre à jsonstring. Si vous avez un jsonobject dans un jsonobject, vous devez créer une classe séparée, comme je le fais dans les classes Student et Subject.

1
Parvathy

Vous pouvez utiliser org.json

    String json = "{ data: { data2 : { value : 'hello'}}}";
    org.json.JSONObject obj = new org.json.JSONObject(json);
    System.out.println(obj.query("/data/data2/value"));
1
GSK