Home > Blockchain >  Java Jackson how to parse large REST API JSON?
Java Jackson how to parse large REST API JSON?

Time:12-27

Api I'm trying to get info from https://prices.runescape.wiki/api/v1/osrs/latest

 HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                    .GET()
                    .uri(URI.create("https://prices.runescape.wiki/api/v1/osrs/latest"))
                    .build();
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            ObjectMapper mapper = new ObjectMapper();
            JsonNode json = mapper.readTree(response.body());
            JsonNode data = json.get("data");
            List<Data> items = new ArrayList<>();
            data.forEach(item -> {
                Data d = new Data(
                        item.get("high").asInt(),
                        item.get("highTime").asInt(),
                        item.get("low").asInt(),
                        item.get("lowTime").asInt()
                );
                items.add(d);

            });

Problem is the object is the itemID. So if I want the item id 6. I can't do it since it's not an attribute of the object.

 "2":{"high":164,"highTime":1672078170,"low":160,"lowTime":1672078164} ``

2 is the itemID and the object.

Below is when I loop through the arraylist and print it out

Data{high=157, highTime=1672071161, low=150, lowTime=1672071151}
Data{high=187987, highTime=1672071066, low=182005, lowTime=1672070881}
Data{high=189903, highTime=1672071052, low=186820, lowTime=1672070884}
Data{high=190000, highTime=1672070957, low=184882, lowTime=1672070984}

CodePudding user response:

Your JSON has the following structure:

{
   "data":{
      "2":{ ... },
      "6":{ ... },
      "8":{ ... },
      "10":{ ... },
      "12":{ ... }
      ...
   }
}

And property "data" is associated not with an object, or a List<Data>, but with a Map<Integer,Data> (or Map<String,Data>.

There are several ways how you can parse:

  • You can define an object with a single property Map<Integer,Data> data.
public static class DataWrapper {
    private Map<Integer, Data1> data;
    
    // getters, setters
}

Usage example:

String json = """
            {
               "data":{ ... }
            }
            """;

ObjectMapper mapper12 = new ObjectMapper();
        
DataWrapper dataWrapper = mapper12.readValue(json12, DataWrapper.class);
Map<Integer, Data1> dataMap = dataWrapper.getData();
    
System.out.println("item 6: "   dataMap.get(6));
  • Another approach would be to create a JsonNode by parsing the given JSON, access the node mapped to the property "data" and parse it as a Map using ObjectReader and its method ObjectReader.readValue(). To generate ObjectReader we can make use of the method ObjectMapper.readerFor() which expects a TypeReference.

That's how the second approach might be implemented:

String json = """
            {
               "data":{ ... }
            }
            """;
        
ObjectMapper mapper = new ObjectMapper();
JsonNode tree = mapper.readTree(json);
        
ObjectReader reader = mapper.readerFor(new TypeReference<Map<Integer, Data>>() {});
Map<Integer, Data> itemsMap = reader.readValue(tree.get("data"));
    
System.out.println("item 6: "   itemsMap.get(6));

Output:

item 6: Data{high=195500, highTime=1672079035, low=182009, lowTime=1672078518}
  • Related