简体   繁体   中英

Parsing Json with Gson, an array without [ ]?

I need to parse this json file, but it's in such a weird format. https://rsbuddy.com/exchange/summary.json I am using Gson, and I have never dealt with Json before so I am quite lost.

"2": {"buy_average": 191, "id": 2, "sell_average": 191, "name": "Cannonball", "overall_average": 191}

After reading this answer Parsing JSON from URL

I have come up with the code here:

    public class AlchemyCalculator {
public static void main(String[] args) throws Exception {

    String json = readUrl("https://rsbuddy.com/exchange/summary.json");

    Gson gson = new Gson();        
    Page page = gson.fromJson(json, Page.class);
    System.out.println(page.items.size());
    for (Item item : page.items)
        System.out.println("    " + item.buy_average);
}


private static String readUrl(String urlString) throws Exception {
    BufferedReader reader = null;
    try {
        URL url = new URL(urlString);
        reader = new BufferedReader(new InputStreamReader(url.openStream()));
        StringBuffer buffer = new StringBuffer();
        int read;
        char[] chars = new char[1024];
        while ((read = reader.read(chars)) != -1)
            buffer.append(chars, 0, read); 

        System.out.println("{items: [" +buffer.substring(1, buffer.length() -1) + "]}");

        return "{items: [" +buffer.substring(1, buffer.length() -1) + "]}";
    } finally {
        if (reader != null)
            reader.close();

    }
}


static class Item {
    int buy_average;
    int id;
    int sell_average;
    String name;
    int overall_average;

}

static class Page {
    List<Item> items;
}
}

I don't understand how to parse it though, I have seen answers that say to set up a matching object heirarchy, but I don't see how to do that here.

Thanks in advance, as well as apologizing in advance for the millions of Json questions on here and me not being able to understand from those.

You can try to use JsonReader to stream the json response and parse it like this :

    Reader streamReader = new InputStreamReader(url.openStream());
    JsonReader reader = new JsonReader(streamReader);
    reader.beginObject();
    while (reader.hasNext()) {
         String name = reader.nextName(); //This is the JsonObject Key
         if (isInteger(name)) {
             reader.beginObject();
             while (reader.hasNext()) {
                 String name = reader.nextName();
                 if (name.equals("id")) {
                     //get the id
                 } else if (name.equals("name")) {
                     //get the name
                 } else if (name.equals("buy_average")) {
                     //get the buy average
                 } else if (name.equals("overall_average")) {
                     //get the overall average
                 } else if (name.equals("sell_average")) {
                     //get the sell average
                 } else {
                     reader.skipValue();
                 }
             }
             reader.endObject();
         }
    }
    reader.endObject();
    reader.close();

where isInteger is a function :

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    if (length == 0) {
        return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
        if (length == 1) {
            return false;
        }
        i = 1;
    }
    for (; i < length; i++) {
        char c = str.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}

If you do want to use Gson to parse the string as list of Item class, there is a workaround which is as following:

    List<Item> itemsOnPage = new ArrayList<Item>(); 
    String content = readUrl("https://rsbuddy.com/exchange/summary.json");  
    Gson gson = new GsonBuilder().create();
    // the json value in content is like key-value pair which can be treated as a map 
    // {2: item1, 3: item2, 4: item4, .....}
    HashMap<String, Object> items = new HashMap<>();
    items = (HashMap<String, Object>) gson.fromJson(content, items.getClass());
    for (String key : items.keySet()) {
        // Once you have converted the json into a map and since the value associated 
        // with it is also a set of key-value pairs it is treated as LinkedTreeMap
        LinkedTreeMap<String, Object> itemMap = (LinkedTreeMap<String, Object>) items.get(key);
        // convert it back to json representation to that we could 
        // parse it to an object of the Item class
        String itemString = gson.toJson(itemMap);
        // what we have now in itemString is like this:
        // {"id": 2, "name": "Cannonball", "buy_average": 191, "overall_average": 193, "sell_average": 192}
        Item item = new Item();
        item = gson.fromJson(itemString, item.getClass());
        // add the current item to the list
        itemsOnPage.add(item);
    }

What you also need to understand is the Json syntax. The structure of json from the above URL is like:

{
   "2": { ...some details related to item... },
   "3": { ...some details related to item... },
   ...
   ...
}

You cannot directly parse it as List<?> because it is not. In Json the list is repsented as Array [item1, item2] (check http://www.w3schools.com/json/ ) while the above representation is a dictionary - an id associated with each item ie

{2: item1, 3: item2, 4: item4, .....} 

where each item in itself has some properties eg

{"id": 2, "name": "Cannonball", "buy_average": 191, "overall_average": 193, "sell_average": 192}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM