38

I want to parse this JSON file in JAVA using GSON :

{
    "descriptor" : {
        "app1" : {
            "name" : "mehdi",
            "age" : 21,
            "messages": ["msg 1","msg 2","msg 3"]
        },
        "app2" : {
            "name" : "mkyong",
            "age" : 29,
            "messages": ["msg 11","msg 22","msg 33"]
        },
        "app3" : {
            "name" : "amine",
            "age" : 23,
            "messages": ["msg 111","msg 222","msg 333"]
        }
    }
}

but I don't know how to acceed to the root element which is : descriptor, after that the app3 element and finally the name element.

I followed this tutorial http://www.mkyong.com/java/gson-streaming-to-read-and-write-json/, but it doesn't show the case of having a root and childs elements.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501

3 Answers3

53

Imo, the best way to parse your JSON response with GSON would be creating classes that "match" your response and then use Gson.fromJson() method.
For example:

class Response {
    Map<String, App> descriptor;
    // standard getters & setters...
}

class App {
  String name;
  int age;
  String[] messages;
  // standard getters & setters...
}

Then just use:

Gson gson = new Gson();
Response response = gson.fromJson(yourJson, Response.class);

Where yourJson can be a String, any Reader, a JsonReader or a JsonElement.

Finally, if you want to access any particular field, you just have to do:

String name = response.getDescriptor().get("app3").getName();

You can always parse the JSON manually as suggested in other answers, but personally I think this approach is clearer, more maintainable in long term and it fits better with the whole idea of JSON.

MikO
  • 18,243
  • 12
  • 77
  • 109
  • 1
    I believe this captures the spirit of JSON much better than a "manual parser" approach – tucuxi May 04 '13 at 20:59
  • Thank you, but the JSON file will not contain only app1, app2, app3, it will be dynamic, so I will not be able to fix the class attributes.. –  May 06 '13 at 10:03
  • @Mehdi see edited code, which is even simpler and allows you to have an arbitrary number of *app* objects in your JSON response, just changing the tipe for a `Map`... Btw, if you'll have an arbitrary number of app objects, you should say it in your original post! ;) – MikO May 06 '13 at 12:05
  • @MikO : Thank you, I did as you said, I changed the whole project and created classes but I get a nullPointerException, can you please check my new question : http://stackoverflow.com/questions/16416965/nullpointerexception-json-parsing-in-java-using-gson Thnk you :) –  May 07 '13 at 10:40
  • I'm having trouble grokking this; what should the getters and setters in the code above look like? – B. Clay Shannon-B. Crow Raven Apr 03 '14 at 23:19
  • 1
    @B.ClayShannon, just standard getters and setters! For example: `public String getName() { return this.name; }` and `public void setName(String name) { this.name = name; }` – MikO Apr 03 '14 at 23:37
  • To read from file, you don't need `BufferedReader`: `gson.fromJson(new FileReader(filename), Response.class)` simply works! – Alex Cohn Jun 09 '15 at 23:23
  • so show an example with `JsonReader` since he literally said he wants to parse a **file** – Krusty the Clown May 21 '23 at 23:43
  • @KrustytheClown as I said, `yourJson` variable in my example can be a `JsonReader` (among other things), so that is _literally_ an example using it! How to actually read a file contents into the `JsonReader` is another question. For that, just use `yourJson = new JsonReader(new FileReader("yourFile.json"))` for example. Actually you have that code in another answer! – MikO May 22 '23 at 13:37
20

I'm using gson 2.2.3

public class Main {

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {

    JsonReader jsonReader = new JsonReader(new FileReader("jsonFile.json"));

    jsonReader.beginObject();

    while (jsonReader.hasNext()) {

    String name = jsonReader.nextName();
        if (name.equals("descriptor")) {
             readApp(jsonReader);

        }
    }

   jsonReader.endObject();
   jsonReader.close();

}

public static void readApp(JsonReader jsonReader) throws IOException{
    jsonReader.beginObject();
     while (jsonReader.hasNext()) {
         String name = jsonReader.nextName();
         System.out.println(name);
         if (name.contains("app")){
             jsonReader.beginObject();
             while (jsonReader.hasNext()) {
                 String n = jsonReader.nextName();
                 if (n.equals("name")){
                     System.out.println(jsonReader.nextString());
                 }
                 if (n.equals("age")){
                     System.out.println(jsonReader.nextInt());
                 }
                 if (n.equals("messages")){
                     jsonReader.beginArray();
                     while  (jsonReader.hasNext()) {
                          System.out.println(jsonReader.nextString());
                     }
                     jsonReader.endArray();
                 }
             }
             jsonReader.endObject();
         }

     }
     jsonReader.endObject();
}
}
Gere
  • 2,114
  • 24
  • 24
  • Thank you :) but why do we have to set `jsonReader.beginObject();` and `jsonReader.endObject();` in each method ? (main and readApp) Thank you :) –  May 04 '13 at 19:33
  • I agree with miko. GSON is a very powerful library for convert JSON-Java Object and viceversa.. I have used it that way in most projects. – Gere May 04 '13 at 21:16
3

One thing that to be remembered while solving such problems is that in JSON file, a { indicates a JSONObject and a [ indicates JSONArray. If one could manage them properly, it would be very easy to accomplish the task of parsing the JSON file. The above code was really very helpful for me and I hope this content adds some meaning to the above code.

The Gson JsonReader documentation explains how to handle parsing of JsonObjects and JsonArrays:

  • Within array handling methods, first call beginArray() to consume the array's opening bracket. Then create a while loop that accumulates values, terminating when hasNext() is false. Finally, read the array's closing bracket by calling endArray().
  • Within object handling methods, first call beginObject() to consume the object's opening brace. Then create a while loop that assigns values to local variables based on their name. This loop should terminate when hasNext() is false. Finally, read the object's closing brace by calling endObject().
Gavyn
  • 379
  • 6
  • 11
VAMSHI PAIDIMARRI
  • 236
  • 1
  • 4
  • 9