To XML and Back: Using JSON in Android

JavaScript Object Notation (JSON) is competing with XML as the data encoding format of choice.

Yesterday’s champion — XML

When it comes to data exchange, the default choice is more often than not XML.

Prior to XML’s arrival, data was typically exchanged via fixed length or delimited data formats. Common delimiters are commas, tabs, pipes, and new line characters. Critics of these formats argue that they are too rigid, so XML grew as a popular alternative.

XML is a text-based, self-describing format with each field wrapped in a “tag” in the same way elements of an HTML file are described with container tags — in fact, HTML is a specific subset of XML.

You can open an XML file in a text editor and make sense of it, though ordinarily an XML file is consumed by a specific application which is expecting the data it contains. For example, most email readers today consume an RSS feed, which is a relatively simple XML format containing information about stories or articles. RSS feeds are found all over the Internet. For example, here is a link for articles from Linux Magazine.

The strength of XML — its easy to read and parse format — is also its weakness. While storage is more plentiful today and networks are faster, there is little need to send all of those verbose tags over the wire.

The new kid in town and potential “heir apparent” to succeed XML as the data exchange format of choice is the JavaScript Object Notation, or JSON.

Introducing JavaScript Object Notation

JSON is based on a subset of the JavaScript language and like XML, is a format designed to organize data. It is less verbose than XML and has a very simple syntax. We discuss JSON here in this article, but you may also care to have a look at http://json.org.

JSON can store “objects” and ordered lists of objects. An “object” may be a string or a number, or even a list of objects — in other words, you can nest JSON objects within one another to an arbitrary depth. In our earlier articles covering WebOS programming we used JSON quite a bit to organize data. Thinking about it, WebOS itself is entirely dependent upon JSON. Increasingly JSON is used in dynamic, client-side programming as you can even store and exchange string representation of JavaScript functions, which are subsequently “eval’d” at run time.

Sample JSON

In this article we take a look at using JSON with a simple Android application. Before we build the application, let’s take a look at a sample of JSON.

I have recently been listening to a book by Richard Stearns, President of World Vision. In doing some research on the man, I came across an interview conducted by business guru .

I was thinking that this would be ideal to read on my mobile phone. This sort of data has ordinarily been made available via XML formatted RSS feeds. I converted this html into JSON for the purposes of this article. What we see below is a subset of the data — the sample application, which you can find from the Linux Magazine Mobile code hosting site, contains the full JSON file.

{
"firstname":"Richard",
"lastname":"Stearns",
"almamater":"Cornell University",
"occupation":"President, World Vision",
"interview":
	{
		"source" : "http://blog.guykawasaki.com/2007/05/ten_or_so_quest.html#ixzz0giEIX0zY",
		"questions":
			[
			{
			"Question": "How much money does World Vision raise every year?",
			"Answer": "Worldwide, World Vision raises about $2 billion annually; the U.S. office, which I head up, raises about half of the total."
			},
			{
			"Question": "Is this the 80/20 rule where twenty percent of the people send in eighty percent of the money or are donations more spread out?",
			"Answer": "World Vision's strength is that we are supported by hundreds of thousands of faithful people who give us about a dollar a day by sponsoring children. Our \"major donors\" account for less than five percent of our total income. Also, for a non-profit, we have quite a diversified portfolio of revenue. Just over forty percent is cash from private citizens; thirty percent is government grants in food and cash; and about thirty percent are products donated from corporation--what we call \"gifts-in-kind.\""
			}
			]
	}
}

Though it is a simple format, it is easy to introduce errors into a JSON object. As such you may want to test your JSON objects outside of your application during development. I was able to make use of to find a missing comma. This site is now in my bookmarks!

Some things to notice about this JSON data:

  • All data is text based, organized into key/value pairs. There is very little “overhead” in this data.
  • Each JSON “object” is delimited by curly braces {}.
  • Note that the value associated with the key “interviews” is a JSON object itself — a nested object.
  • The “questions” value is an array of JSON objects, each containing two key/value pairs.
  • Double quotes are escaped with a backslash, just as in Java and C programming environments.

Now that we’ve got a feel for what JSON looks like, let’s build an Android application using JSON.

Sample Application

The focus of this application is on parsing JSON data and manipulating it within Android. In order to work with JSON within an Android application, we must import the package org.json:

import org.json.*;

This package contains a few classes. We will use the classes JSONObject and JSONArray. For more info on this package, have a look at the Android docs online.

Our application has a very simple layout, two Buttons and a TextView. Of note, the TextView is contained within a ScrollView. The reason for this is that our data extracted from the JSON file is more than a screen-ful, so we want the user to have an easy means of accessing all of the data. The ScrollView takes care of all of this scrolling for us. Note also the use of a LinearLayout with a horizontal orientation to hold the two Buttons. Here is the main.xml file from the project.

<?xml version="1.0" encoding="utf-8"?&rt;

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &rt;

<LinearLayout
	android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
	   &rt;

<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnTest" android:text="Test JSON"&rt;</Button&rt;
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnTestFile" android:text="Parse JSON file"&rt;</Button&rt;
</LinearLayout&rt;

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ScrollView01" android:layout_width="fill_parent" android:layout_height="wrap_content"&rt;

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text=""
    android:layout_gravity="center_horizontal"
    android:id="@+id/txtStatus"
    android:isScrollContainer="true"/&rt;

</ScrollView&rt;
</LinearLayout&rt;

Parsing JSON

So, how do we parse JSON? Simple, we use the constructor of the JSONObject() which takes a string. In the first example we use a statically defined Java String which contains a simple JSON object.

String staticObject = "{\"firstname\":\"Steve\",\"lastname\":\"Jobs\",\"cellphones\":\"0\"}";

void buildObject()
{
	try
	{
		obj = new JSONObject(staticObject);
		String x = obj.get("firstname").toString() + " " + obj.get("lastname").toString() + " has " + obj.getInt("cellphones") + " Android phones.";
		setStatus(x);
	}
	catch (JSONException je)
	{
		setStatus("Error occured " + je.getMessage());
	}
}

void setStatus(String x)
{
	TextView tv = (TextView) findViewById(R.id.txtStatus);
	tv.setText(x);
}

This code takes the following steps:

  • Creates a new JSONObject, passing in a String representing a JSON object.
  • Constructs a String (x) by extracting elements from the parsed JSON object.
  • Setting the contents of a TextView with the constructed String.

Here is a screen shot of this code running.

Simple JSON parsing
Simple JSON parsing

The second JSON example parses “raw” resource containing a representation of the Kawasaki/Stearns interview.

The interview is stored as a text file under the “raw” folder beneath the res folder within the Android project. Note that the raw folder is not created by default by the Android Developer Tools — you need to create that yourself. Here is a screen shot of the Android project.

The interview in the Android project
The interview in the Android project

Here is the code used to read in the resource, parse it and construct a string to view the data. Note that we could represent this data as something other than a string — and we’ll take a look at that in a future article.

void buildObjectFromFile()
{
	try
	{
		String x = "";
		InputStream is = this.getResources().openRawResource(R.raw.interview);
		byte [] buffer = new byte[is.available()];
		while (is.read(buffer) != -1);
		String json = new String(buffer);
		obj = new JSONObject(json);
		x = obj.getString("firstname") + " " + obj.getString("lastname") + "\n";
		x += obj.getString("occupation") + "\n";

		JSONObject interview =  obj.getJSONObject("interview");
		x += "Interview source:" + interview.getString("source")  + "\n";

		JSONArray questions = interview.getJSONArray("questions");
		x += "Number of questions: " + questions.length()  + "\n\n";

		int i;
		for (i=0;i<questions.length();i++)
		{
			JSONObject qa = questions.getJSONObject(i);
			x += "------------\n";
			x += "Q" + (i+1) + ". " + qa.getString("Question") + "\n\n";
			x += "A" + (i+1) + ". " + qa.getString("Answer") + "\n";
		}
		setStatus(x);
	}
	catch (Exception je)
	{
		setStatus("Error w/file: " + je.getMessage());
	}
}

Here are a few things to note about this code sample.

  • We access the resource with a call to getResources().openRawResource(…), using the auto-generated identifier R.raw.interview.
  • After reading in the data and converting it to a java.lang.String, we parse it in the constructor of the JSONObject.
  • Extracting the interview object is accomplished by calling getJSONObject(), in the same way we extract a String with getString(), except in this case a JSONObject is returned instead of a String.
  • Extracting the questions “ordered list/collection” is accomplished with a call to getJSONArray(). Each element of the array is a JSONObject itself.
JSONArray questions = interview.getJSONArray("questions");

We extract the number of objects in the questions array via the length() method.

Next, we iterate through the questions, formatting a string and then wrap up by setting the value of the TextView with our formatted interview text.

The interview questions
The interview questions

Admittedly, the GUI isn’t very exciting — we need to make better use of the available Android UI widgets — a task we’ll undertake in an upcoming article.

And by the way, if you have ever wondered just what one person can do to make “the world a better place”, consider lending a hand to a child through World Vision.

Fatal error: Call to undefined function aa_author_bios() in /opt/apache/dms/b2b/linux-mag.com/site/www/htdocs/wp-content/themes/linuxmag/single.php on line 62