1

I am currently working on a project where I am using the Steam Web API. The API returns data in JSON format and I wanted to make a Java program that uses this data. Here is the following JSON format from the API:

{
    "response": {
        "players": [
            {
                "steamid": "---",
                "communityvisibilitystate": 1,
                "profilestate": 1,
                "personaname": "---",
                "lastlogoff": 1429915502,
                "profileurl": "---",
                "avatar": "---",
                "avatarmedium": "---",
                "avatarfull": "---",
                "personastate": 0
            }
        ]

    }
}

I am using Google's JSON API called Gson and I am having trouble setting up the Java classes so that I can use the fromJson() method.

From the JSON data, I know that there is an array of players objects that contain all the data. The one thing that is confusing me is the outer tag called response. I know that I have to construct a class representing the players objects but do I also have to create a class that represents response since it encloses players?

As of right now, I have a file named Response.java that contains the following:

public class Response {

    private ArrayList<Player> playerSummaries = new ArrayList<Player>();

    public String toString() {
        return playerSummaries.get(0).toString();
    }

}


class Player {
    private String steamid;
    private String personaname;


    public String getSteamID() {
        return steamid;
    }

    public void setSteamID(String newSteamID) {
        steamid = newSteamID;
    }

    public String getPersonaName() {
        return personaname;
    }

    public void setPersonaName(String name) {
        personaname = name;
    }

    //Rest of getters and setters omitted.

    @Override
    public String toString() {
        return "<<" + "steamid=" + steamid + "\n" + "name=" + personaname + "\n" + ">>";
    }
}

I only included the variables that I plan to use. The JSON data above is contained in a String called jsonData and this is what I am testing in my main method:

Response response = gson.fromJson(jsonData, Response.class);

System.out.println(response.getPlayerAt(0));

However, running this gives me an IndexOutOfBoundsException. It seems as if Gson was unable to get the information and store it into an object? Could anyone shed some light on this problem I am having? I am mostly curious to know if I have set up my classes correctly.

Rowen McDaniel
  • 169
  • 1
  • 2
  • 11
  • do you want to return a player at index 0 or to iterate the whole arraylist? – kirti Apr 25 '15 at 04:12
  • When it comes to writing POJO classes that match a JSON schema I find quite useful to compare my code with the one automatically generated by online tools such as http://www.jsonschema2pojo.org/ – Javide Apr 25 '15 at 04:18
  • @kirti I am only returning the player at index 0 for testing purposes. – Rowen McDaniel Apr 25 '15 at 04:20

2 Answers2

3

Replace

private ArrayList<Player> playerSummaries = new ArrayList<Player>();

with

private ArrayList<Player> players = new ArrayList<Player>();

GSON uses reflection to look up which field it should populate. In your case it is looking up whether you have a field named players which you do not.

You also do not need to instantiate the field, GSON will do that for you.

EDIT:

You also need a wrapper class around your top-level object. So

class MyObject {
    public Response response;
}

MyObject myObject = gson.fromJson(jsonData, MyObject.class);
Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
  • I have changed the `playerSummaries` to `players` but had to keep the `new ArrayList()` or else I would get a NullPointerException. However I am still getting IndexOutOfBoundsException when trying to access the first element in the ArrayList. Do you know if accessors and mutators are required for this to work? – Rowen McDaniel Apr 25 '15 at 03:53
  • Make sure you do `MyObject myObject = gson.fromJson(...)` – Martin Konecny Apr 25 '15 at 04:00
  • I have added the `MyObject` class to `Response.java` and made the changes that you suggested but I am still getting the same exception. The size of `players` is still 0. – Rowen McDaniel Apr 25 '15 at 04:12
  • Okay so I was able to get this working by nesting the `Response` and `Player` inside the wrapper class `MyObject`. However I am a little confused as to why this worked. I would appreciate it if someone could explain the structure of the JSON file to me, what exactly is the string `response` called that surrounds the `players` array? – Rowen McDaniel Apr 25 '15 at 04:38
  • `{}` is an object in GSON. So you need to map `{response: {}}` (two objects) directly to `public class MyObject {public Response response; }` (two classes) – Martin Konecny Apr 25 '15 at 04:41
  • So if I were to remove the `"response":` and the outer set of `{ }`, I would be left with an array of `players` objects? I'm still new to JSON and just want to be sure. – Rowen McDaniel Apr 25 '15 at 04:47
  • `{}` maps to `public class MyObject {}`. `{response: 5}` maps to `public class MyObject { int response;}`. To answer your question, if your json was just `[1, 2, 3]`, you would need to map it to a list `List` but this is not recommended. With JSON your top level element you should always be an object, not a list. – Martin Konecny Apr 25 '15 at 05:16
0

Why you are using

System.out.println(response.getPlayerAt(0));

You should use

response.getPlayerSummaries.get(0); 

where getPlayers is the getter of your

   private ArrayList<Player> playerSummaries = new ArrayList<Player>();

getPlayerSummaries will get the arraylist and then you will use get method of arraylist class over it.

kirti
  • 4,499
  • 4
  • 31
  • 60