0

I'm trying to learn JSON parsing, and a quick question came up regarding how to parse JSON in which the "category" name can change based on the request from an external API (specifically a video game API I'm toying with).

As a random example, sending the API request with "laofuthetiger" as the URI returns JSON that looks like this:

{ "laofuthetiger": {
   "id": 51044840,
   "name": "Lao Fu the Tiger",
   "profileIconId": 664,
   "revisionDate": 1484537981000,
   "summonerLevel": 30
}}

Changing the URI to "sloverlord" yields this:

{ "sloverlord": {
   "id": 39943538,
   "name": "sloverlord",
   "profileIconId": 712,
   "revisionDate": 1484537981000,
   "summonerLevel": 30
}}

From my elementary understanding of JSON parsing using GSON, I'm able to gather data from the first JSON example by having a class that looks like this:

public class Player{
   private SummonerDto laofuthetiger;
...

where SummonerDto contains the individual elements id, name, etc. However, I don't know how to handle the actual "category" (or however it's called) changing between API calls. With this solution, a call using laofuthetiger works but sloverlord would return an internal error for obvious reasons.

EDIT: For a bit more information, the URI looks something like this: dev.host.com/get_player_by_name/laofuthetiger?api_key=XXXXX where "laofuthetiger" can be any player name.

zeBugMan
  • 435
  • 1
  • 6
  • 9

2 Answers2

1

Using GSON

import java.util.Map; 

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

JsonParser parser = new JsonParser();
//e.getKey() is actual 'category' name
//e.getValue() is raw JsonObject
Map.Entry<String, JsonElement> e = ((JsonObject)parser.parse(jsonString)).entrySet().iterator().next();
Gson g = new Gson();
SummonerDto dto = g.fromJson(e.getValue(), SummonerDto.class);

Using Jackson

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper om = new ObjectMapper();
JsonNode tree = om.readTree(jsonString);
JsonNode dtoNode = tree.get(0);
SummonerDto dto = om.readValue(om.treeAsTokens(dtoNode), SummonerDto.class);

UPDATE

Added full code for GSON

import java.io.IOException;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class Test {

    private static final String JSON = "{ \"laofuthetiger\": {" + "\"id\": 51044840,"
            + "\"name\": \"Lao Fu the Tiger\"," + "\"profileIconId\": 664," + "\"revisionDate\": 1484537981000, "
            + "\"summonerLevel\": 30" + "}}";

    public static void main(String[] args) throws IOException {
        JsonParser parser = new JsonParser();
        Map.Entry<String, JsonElement> e = ((JsonObject) parser.parse(JSON)).entrySet().iterator().next();
        Gson g = new Gson();
        SummonerDto dto = g.fromJson(e.getValue(), SummonerDto.class);

        System.out.println(dto);
        }

    class SummonerDto {
        int id;
        String name;
        int profileIconId;
        long revisionDate;
        int summonerLevel;

        @Override
        public String toString() {
            return "SummonerDto [id=" + id + ", name=" + name + ", profileIconId=" + profileIconId + ", revisionDate="
                    + revisionDate + ", summonerLevel=" + summonerLevel + "]";
        }

    }

Output

SummonerDto [id=51044840, name=Lao Fu the Tiger, profileIconId=664, revisionDate=1484537981000, summonerLevel=30]

rkosegi
  • 14,165
  • 5
  • 50
  • 83
0

There's an option:

You always know the name of your player right?

When you can your API, it's something like this:

    mPlayer = "laofuthetiger";

    Repository mRepo = new Repo();
    mRepo.requestPlayerByName(player)

[when you get your response]

 private void getMyResponseFromAPI(Json jsonResponse){
     JsonObject jSummoner jsonResponse.get(mPlayer).getAsJsonObject()
     SummonerDto summoner = new Gson().fromJson(jPlayer, Summoner.class)

     Player player = new Player(summoner)
 }

This way you will always get your response, independently of the name of your Player (or summoner).

Why does it works?

The only part that changes in your API response is the Summoner name... the rest of the response always follow the same pattern. So, one you get the Json object with the correct name, You will always have this:

{
   "id": 51044840,
   "name": "Lao Fu the Tiger",
   "profileIconId": 664,
   "revisionDate": 1484537981000,
   "summonerLevel": 30
}

And this is really is to parse with Gson (or Jackson).

Leandro Borges Ferreira
  • 12,422
  • 10
  • 53
  • 73