Lab: Web APIs, JSON and JSON-LD

From Info216

Lab 5: Accessing and lifting Web APIs (RESTful web services)


Programming regular (non-semantic) as well as semantic Web APIs (RESTful web services) with Jena, JSON and JSON-LD.

Tip: Newer versions of JSON-LD have been released since INFO216 started. apache-jena-3.2.0 uses a newer JSON-LD library (0.9.0) than the previous verion. Because JSON-LD is so new, this may make a difference, so please consider upgrading!


  • Object, Map HashMap (put, get, remove), List, Vector
  • Model (read)
  • JsonUtils (toPrettyString)
  • JsonLdOptions (setExpandContext)
  • JsonLdProcessor (compact, expand, flatten)
  • IOUtils (toInputStream)

Object, Map HashMap (add, get), List, Vector are parts of the basic Java API (JavaDoc here: The other classes are all available through Jena, but Jena does not include JavaDoc for all of them. This ZIP-archive contains JavaDoc for the Java implementation of JSON-LD (unpack it, for example to your Jena-folder, and open the file index.html in a browser).

Also, because JSON-LD is quite new, there are not yet many good tutorials available. This lab outline is therefore a little more detailed than the previous ones!


Write a small program that accesses the GeoNames web API ( and download the result. For example, you can use this URL to access more information about Ines' neighbourhood in Valencia: . You can use the getJsonBody method (attached to the end of this message) to write this program. (If you call getJsonBody from the static main method in your program, you must define getJsonBody as static too).

The getJsonBody method returns a JSON object, which is either a Java List or a HashMap. Use the toPrettyString method in the JsonUtils class to format and then print your JSON object.

You do not have to use the GeoNames web API. There are lots and lots of other web APIs out there. But we want something simple that does not require registration (HTTPS can also make things more complex when the certificates are outdated). Here are some examples to get you started if you want to try out other APIs: , , , /intro , .

Be nice! While you are testing things, write a new method getJsonBodyProxy. This method takes a URL parameter just like the original getJsonBody. But it never connects to that URL. Instead, it returns a jsonObject created locally from a results string you have copied into your program. By letting the rest of your program call the new getJsonBodyProxy instead of getJsonBody while you are debugging your code, you do not need to call the GeoNames API over and over.

Here is an example of a results string you can use, if you have trouble connecting to GeoNames (note that you have to escape all the quotation marks inside the Java string): {\"postalcodes\":[{\"adminCode2\":\"V\",\"adminCode1\":\"VC\",\"adminName2\":\"Valencia\",\"lng\":-0.377386808395386,\"countryCode\":\"ES\",\"postalcode\":\"46020\",\"adminName1\":\"Comunidad Valenciana\",\"placeName\":\"Valencia\",\"lat\":39.4697524227712}]}"

So far we have only used plain JSON. Now we want to move to JSON-LD. Make a new HashMap (and therefore also a JSON object) called context. Add at least one pair of strings to it. For example the pair "lat" and "". You can also add the pair "lng" and "". Create a JsonLdOptions object and set its expand context to be the context object with the pair of strings in.

Use the JsonLdProcessor to expand your jsonObject and pretty print the result. Has anything happened? Why/why not?!

Add this pair too to the context object: "postalcodes" and "". Rerun. Has anything happened now? Why/why not?!

Add more string pairs, using existing or inventing new terms as you go along, to the context object and rerun expand. The expanded JSON object lifts the data from the web API. It can be used to provide a semantic version of the original web API.

In addition to expand, try the compact and flatten operations on the JSON object. What do they do?

Go back to the RDF/RDFS programs your wrote in labs 2 and 3. Extend the program so that it adds further information about the post codes of every person in your graph.

We will now make a Jena model from the JSON-LD object. To do this, first create a new default Jena model. Then convert the JSON-LD object to a string (use JsonUtils.toPrettyString). Then turn the string into an input stream (use IOUtils.toInputStream, with "UTF-8" as character set). Then read the input stream into your Jena model (use (There may be other ways to move from JSON object to Jena models, but this is a simple and straightforward way to start.)

Congratulations - you have now gone through the steps of accessing a web API over the net, lifting the results using JSON-LD, manipulating the in JSON-LD and reading them into a Jena RDF model. Of course, it is easy to convert the Jena model back into JSON-LD using model.write(..., "JSON-LD") ...

 /**    Vi brukeraksesserer vev-API-ene på enklest mulig måte, siden det er Jena og JSON-LD
        som er fokus i INFO216, ikke selve vevprogrammeringen.
   static Object getJsonBody(URL serverAddress) {
       Object jsonObject = null;
       HttpURLConnection connection = null;
       try {
           // send GET request
           connection = null;
           connection = (HttpURLConnection)serverAddress.openConnection();
           // parse JSON reponse
           jsonObject = JsonUtils.fromInputStream(connection.getInputStream());
       } catch (MalformedURLException e) {
       } catch (ProtocolException e) {
       } catch (IOException e) {
           // close the connection
           connection = null;
       return jsonObject;