Disposition Posted May 15, 2016 Share Posted May 15, 2016 (edited) With this you can lookup: Price Icon (32x32 normal and 96x96 large) Description Name Others I've also included some caching to minimize API lookups but you can disable this if you want. Usage: Create a new instance of the API: GrandExchangeApi api = new GrandExchangeApi(); Look up an item: GELookupResult result = api.lookup(itemId); Get data about the item: int price = result.price; String iconUrl = result.smallIconUrl; String description = result.description; //etc Snippet: import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Utility class for access to the Grand Exchange API. */ public class GrandExchangeApi { /** * The URL of the API endpoint. */ private static final String API_LOCATION = "http://services.runescape.com/m=itemdb_oldschool/api/catalogue/detail.json?item=%d"; /** * The cache in which items that have already been looked up are stored. */ private final Map<Integer, GELookupResult> cache; /** * Creates a new Grand Exchange API instance, with caching enabled. */ public GrandExchangeApi() { this(true); } /** * Creates a new Grand Exchange API instance. * @param cache Whether to enable caching of results. */ public GrandExchangeApi(boolean cache) { if(cache) { this.cache = new HashMap<>(); } else { this.cache = null; } } /** * If caching is enabled, clears the cache so that new results are fetched on lookup. */ public void flushCache() { if(cache != null) { cache.clear(); } } /** * Looks up an item using the Grand Exchange API. This method blocks while waiting for the API result. * @param itemId the id to look up. * @return the result returned by the api. May be null if an error has occurred. */ public GELookupResult lookup(int itemId) { if(cache != null) { GELookupResult result = cache.get(itemId); if(result != null) { return result; } } String json; try { URL url = new URL(String.format(API_LOCATION, itemId)); Scanner scan = new Scanner(url.openStream()).useDelimiter("\\A"); json = scan.next(); scan.close(); } catch(IOException e) { return null; } GELookupResult result = parse(itemId, json); if(cache != null) { cache.put(itemId, result); } return result; } /** * Parses a GELookupResult from the JSON returned by the API. * @param itemId The item ID. * @param json The JSON returned by the server. * @return The serialized result. */ private static GELookupResult parse(int itemId, String json) { Pattern pattern = Pattern.compile("\"(?<key>[^\"]+)\":\"(?<value>[^\"]+)\""); Matcher m = pattern.matcher(json); Map<String, String> results = new HashMap<>(); while(m.find()) { results.put(m.group("key"), m.group("value")); } int price = 0; Matcher priceMatcher = Pattern.compile("\"price\":(?<price>\\d+)").matcher(json); if (priceMatcher.find()) { price = Integer.parseInt(priceMatcher.group("price")); } return new GELookupResult( results.get("icon"), results.get("icon_large"), results.get("type"), results.get("typeIcon"), results.get("name"), itemId, price ); } /** * A class representing a result from an API lookup. */ public static final class GELookupResult { public final String smallIconUrl, largeIconUrl, type, typeIcon, name; public final int id, price; private GELookupResult(String smallIconUrl, String largeIconUrl, String type, String typeIcon, String name, int id, int price) { this.smallIconUrl = smallIconUrl; this.largeIconUrl = largeIconUrl; this.type = type; this.typeIcon = typeIcon; this.name = name; this.id = id; this.price = price; } } } Edited May 15, 2016 by Disposition 5 Quote Link to comment Share on other sites More sharing options...
liverare Posted May 15, 2016 Share Posted May 15, 2016 Nice work. Caching the results is good practice, but not unless those cached results get updated too. Otherwise the information (such as price) will be out-of-date for the more volatile items. That link gives a small JSon summary of the item, so don't worry about overloading Jagex's servers with requests. Just as long as it's not thousands of requests in a few short seconds, you'll be fine. They're a big and successful company. I'd suggest updating items every 2 minutes. The best way to update the cache would be for the cached items to be mutable. It'll take a bit of tweaking to work, but avoid adding/removing directly to the cache, because that's inefficient. 1 Quote Link to comment Share on other sites More sharing options...
Disposition Posted May 15, 2016 Author Share Posted May 15, 2016 Thanks for the feedback!I know the caching is pretty rudimentary, but as far as I know GE prices only update once a day so it's not really a significant problem. Hadn't thought of making the results mutable though, the only problem I can see with doing that is in situations when you want to store the result as it was when you looked it up (maybe to monitor price changes). Quote Link to comment Share on other sites More sharing options...