JSON Parser tutorial for Android using JSONObjects

Introduction and sample data


JSON is currently one of the more widely used formats for data exchange between various languages and services. While developing for Android, you will often come across situations where you would be required to parse JSON responses from servers. We will use the following example available at the JSON site.

[sourcecode language="java"]
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
[/sourcecode]

The JSON data shown above has numerous nested objects, name-value pairs and also an array.

Data Analysis


Just a low down on JSON before we begin implementing the parser. JSON is basically a collection of nested name-value pairs where the names are strings and the values could be strings, integers, doubles, objects, etc. (Of course, represented in a string format). Analyzing our sample data will give us a clearer idea.

Each object is encapsulated in {…}. So here the outermost set of {…} defines the root object. Inside are defined nested objects such as glossary, GlossDiv, GlossList, GlossEntry, etc. The objects also include name-value pairs. If you look at the GlossEntry object, the member variables are ID, SortAs, GlossTerm, etc. In our example, these are all string values, but these could have been any of the basic data types such as integer, real, etc.

Now observe the object GlossDef, you will see that it contains a JSON array which is denoted by [...]. JSON can contain array of the normal data types and also objects. In our case we have an array of strings, with the value GML, XML.

JSON and Android


You can use either the JSONObject found in the org.json library or the JSONReader found in android.util. In the following tutorial we will be learning how to use JSONObject to parse our JSON data. This is because, the JSONObject has been a part of android since API level 1 while JSONReader has been added more recently, since API Level 11. So if you plan to support your application for older Android versions, be careful with your choice of implementation.

JSON Parser


Here is the code for the JSON Parser which parses the sample data provided above and displays it in a TextView.

[sourcecode language="java"]
private boolean parse(String strJson){

if( strJson.contentEquals("") ){
return false;
}

try {
//Main object
JSONObject mainObj = new JSONObject(strJson);
Log.i(TAG, "Main OBJ : " + mainObj.length() + " items.");
output += "MAIN OBJ ["+mainObj.length()+"]\n";

//Glossary object
JSONObject glossaryObj = mainObj.getJSONObject("glossary");
Log.i(TAG, "Glossary OBJ : " + glossaryObj.length() + " items.");
output += "\tGLOSSARY OBJ ["+glossaryObj.length()+"]\n";

String glossTitle = glossaryObj.getString("title");
output += "\t\tTitle : "+glossTitle+"\n";
//GlossDiv Object
JSONObject glossDivObj = glossaryObj.getJSONObject("GlossDiv");
output += "\t\tGLOSS DIV OBJ ["+glossDivObj.length()+"]\n";

String glossDivTitle = glossDivObj.getString("title");
output += "\t\t\tTitle : "+glossDivTitle+"\n";
//GlossList object
JSONObject glossListObj = glossDivObj.getJSONObject("GlossList");
output += "\t\t\tGLOSS LIST OBJ ["+glossListObj.length()+"]\n";

//GlossEntry object
JSONObject glossEntryObj = glossListObj.getJSONObject("GlossEntry");
output += "\t\t\t\tGLOSS ENTRY OBJ ["+glossEntryObj.length()+"]\n";

//Read the fields of GlossEntity
HashMap<String, String> glossEntryInfo = new HashMap<String, String>();
glossEntryInfo.put("ID", glossEntryObj.getString("ID"));
glossEntryInfo.put("SortAs", glossEntryObj.getString("SortAs"));
glossEntryInfo.put("GlossTerm", glossEntryObj.getString("GlossTerm"));
glossEntryInfo.put("Acronym", glossEntryObj.getString("Acronym"));
glossEntryInfo.put("Abbrev", glossEntryObj.getString("Abbrev"));
glossEntryInfo.put("GlossSee", glossEntryObj.getString("GlossSee"));

for( Entry<String,String> entry : glossEntryInfo.entrySet() ){
output += "\t\t\t\t\t"+entry.getKey()+" : "+entry.getValue()+"\n";
}
//Read the GlossDef object
JSONObject glossDefObj = glossEntryObj.getJSONObject("GlossDef");
output += "\t\t\t\t\tGLOSS DEF OBJ ["+glossDefObj.length()+"]\n";

String glossDefPara = glossDefObj.getString("para");
output += "\t\t\t\t\t\tpara : "+glossDefPara+"\n";

//Read the JSON Array
JSONArray glossSeeAlsoArray = glossDefObj.getJSONArray("GlossSeeAlso");
output += "\t\t\t\t\t\tGlossSeeAlso : "+glossSeeAlsoArray.length()+" entries\n";

for(int i = 0; i < glossSeeAlsoArray.length(); i++ ){
output += "\t\t\t\t\t\t\t\t"+glossSeeAlsoArray.getString(i)+"\n";
}

} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}

return true;
}
[/sourcecode]

Explanation and suggestions


Create the root object as a JSONObject. It’s constructor takes a string as input. We call the getType(String name) where the Type could be either a JSONObject, a JSONArray or a basic data type. These methods return data if the value is of Type or if the value can be converted to the requested Type.

There is another method of the form optType(String name, Type optional), where the variable is optional. The user can specify a default value which is returned if the field is missing.

In our example, we use the getString() extensively as most of the fields are string fields. In the GlossDef object, one of the fields [GlossSeeAlso] is of the array type. We have used the getJSONArray() method to obtain it.

The length() method returns the size of the array in case of JSONArray and the number of member variables in case of the JSONObject.

The Final review


We learnt,

  • basics of JSON
  • how to write a JSON parser using the JSONObject.

You can find the code here.

WITER – AsyncTask… What? Why? How?

The Problem


In the previous post, we learnt how to receive data from a server. One of the requirements was to complete the long running task of receiving the data in a thread other than the UI thread. This was to avoid the Application Not Responding (ANR) problem. We chose AsyncTask to do this. Here we explain the what, why and how of the AsyncTask.

For more info on the application that we are building, click here.

The What and the Why?


As per the general working of an android application, everything happens in a single process in a single thread (unless otherwise specified). The main thread is the UI thread and all UI activities are to be done in this. Android suggests that no long running task should be done that could block the UI. If you do, then be sure to meet any android developer’s arch nemesis, the ANR! To avoid such scenarios, Android suggests using worker threads which take care of the heavy tasks and then use the main UI thread to update the UI.

This can be done using normal threads but Android was kind enough to provide a special way to perform such asynchronous tasks. Given the fact that multi-threading is an integral part of the design, AsyncTask definitely makes a developer’s life lot simpler.

The Android Developer’s site has to say the following about AsyncTask which is exactly what it is,

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

The How


Let us now get on to the more interesting part of the AsyncTask. But before that lets us just list down the main methods that you must know to use it in an optimum way.

  • AsyncTask: This is the class declaration and must be subclassed in order to be used. The 3 generic types must be specified at the time of subclassing. They are,
    1. Params: This is the type that is sent when execute() is called. They are the parameters that would be required by the background execution. The parameters are always sent as an array.
    2. Progress: You can update the UI at regular intervals while the background execution is carried on. This type provides the unit in which the progress is to be reported. Eg int for a progressbar, String for progress messages.
    3. Result: This is used to specify the result type. Could be a computed value, a boolean to notify success.
  • Following are the 5 methods that have to be implemented to get the AsyncTask functioning well.

  • onPreExecute(): This method is called as soon as we call execute() on the AsyncTask object. The method is called on the UI thread and as a result UI activities like setting up progress bars, initializing views etc can be done here.
  • doInBackground(Params… params): This is where all the stuff happens and is a mandatory method to be implemented to get an AsyncTask up and running. All tasks running here are done in a separate thread. To update the UI with any progress, publishProgress(Progress…) can be used. We can either send string messages as updates or units of whatever progress type we have defined.
  • onProgressUpdate(Progress… values): This is another method which runs on the UI thread and updates the UI with the progress of the task. The data sent by publishProgress(Progress…) is received here and utilized for updating the UI.
  • onPostExecute(Result result): This is called after the task is completed. The return value of the doInBackground(Params… params) is received here. For example, you could receive a boolean value to denote whether the task was successful or not.
  • onCancelled(Result result): This method is used to handle the UI activities if the action is cancelled midway. The result from doInBackground(Params… params) is received here, so that it can be used to handle the Cancel scenario. This has been introduced in API 11. Prior to this the method onCancelled() is used. It runs on the UI thread after cancel(boolean) is invoked and doInBackground() has finished.

Under the hood


In our previous post, we had written the HttpManager core code inside the AsyncTask. Here is the skeleton code of the AsyncTask. Since our HttpManager doesn’t require progress updates, we have not implemented the onProgressUpdate(Progress… values) method. HttpQuery is the extended AsyncTask() which has a constructor that is used to pass all the parameters that are required in the methods of the HttpQuery.

[sourcecode language="java"]
public class HttpQuery extends AsyncTask<String, String, Boolean>{

private Context mContext = null;
private HttpClient mClient = null;
private HttpGet mRequest = null;
private HttpResponse mResponse = null;

public HttpQuery( Context context, HttpClient client ) {
mContext = context;
mClient = client;
mRequest = new HttpGet();
}

@Override
protected Boolean doInBackground(String… url) {

}

@Override
protected void onCancelled() {
//Just call the super for this case.
//We call this since we hare using an API level
//less than 11.
super.onCancelled();
}

@Override
protected void onPreExecute() {

}

@Override
protected void onPostExecute(Boolean result) {

}
}
[/sourcecode]

We override the onPreExecute() to start a progress dialog and also implement the onCancel of the dialog, so that our user can stop updating the latest info if he wishes to do so.
[sourcecode language="java"]
protected void onPreExecute() {
mProgress = ProgressDialog.show(mContext, "Updating…", "Fetching Forex Rates…");
mProgress.setCancelable(true);
mProgress.setOnCancelListener(new OnCancelListener() {

@Override
public void onCancel(DialogInterface dialog) {
cancel(true);
}
});
super.onPreExecute();
}
[/sourcecode]

The doInBackground() takes the url that is to be downloaded and on success returns a true. The http related code has been explained in the previous post.
[sourcecode language="java"]
protected Boolean doInBackground(String… url) {
try {
mRequest.setURI(new URI(url[0]));
mResponse = mClient.execute(mRequest);
Log.i(TAG, mResponse.getStatusLine().getReasonPhrase());
return true;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (URISyntaxException e) {
Log.i(TAG, "Please check the Url!");
e.printStackTrace();
return false;
}
}
[/sourcecode]

The onPostExecute() gets the result from the method above and based on it displays a message. And then dismisses the dialog.
[sourcecode language="java"]
protected void onPostExecute(Boolean result) {
Log.i(TAG, "Step 5");
if( result ){
mProgress.setMessage("Succesfully Downloaded!");
Log.i(TAG, "Successfully Downloaded!");
}else{
mProgress.setMessage("Failed to download :( ");
Log.i(TAG, "Failed to download :( ");
}
mProgress.dismiss();
super.onPostExecute(result);
}
[/sourcecode]

Final Review


We learnt,

  • How to extend an AsyncTask to perform a long running task in a worker thread and as a result avoid an ANR.
  • The various methods in the Asynctask that can be overridden and what they do.
  • How to add a progress dialog and dismiss it while a long running task is run in the background.

The code provided in the previous post will suffice. Run it and observe the progress dialog. You can also check the LogCat in your Eclipse for the success/fail messages.

WITER – A simple HttpManager with the Apache Http Client

The Problem


We are building an app, [WITER], which gives us the exchange rates and we are using a free open source API available at . The API returns a JSON string containing the current rates. Our first task is to get the information from the web. How do we manage the data downloading?

For more info on WITER, click here.

The Basics


Early on in your Android development, you will realize that, your app will be required to send/receive data from the internet. It could be content from a server, a response to a request you post, or just plain sending information to some site.

There are 2 ways, in which this can be done. You can either use HttpUrlConnection (I’ll deal with this later in another tutorial) or Apache Http Client. The reason I chose Apache Http Client is because it is the more widely used client. It is more powerful, stable and has a lot more features. While I mentioned HttpUrlConnection is because the Android team is actively working on this in improving it. They have claimed here on their site that they no longer work on the Apache Http Client. Nevertheless, it serves our requirement.

For WITER, what we need is a HttpManager. A Manager that would take care of sending and receiving data. It should do it asynchronously because one of the most important things in android development is NEVER DO AN EXTENDED TASK ON THE UI THREAD or be prepared the face the wrath of ANR (Activity Not Responding). So any such data related task must always be done on a separate thread.

In the following section we will see how we can address our requirements and what are the components of the Apache Http Client that will help us achieve this.

The Components


In the current simple form of the HttpManager, we will just require,

  1. HttpClient: This is your basic interface to the Apache client. There are a number of overloaded execute() methods which you can use based upon your requirement.
  2. HttpGet: The http method that you will be using. This is the method we will be using in our case, but you could use any of the others such as HttpPost, HttpPut, HttpHead. [Tip! Use HttpHead to check the meta information of your request response without downloading the whole body of the response.]
  3. HttpResponse: You will receive an object of this class as a response to calling execute() on the HttpClient. The HttpResponse contains a HttpEntity which in turn contains the content of the response. This http entity also gives you some meta information such as length, type and whether it is part of a stream, is chunked or is repeatable.

That is pretty much all that you will need at the moment to get started. I have wrapped the whole thing in an AsyncTask to address our requirement of running it in a separate thread. Do not worry about it for the time being and just concentrate on the Http part. I will explain AsyncTask in the next post.

Under the hood


So let us begin the actual coding. We create a new package called com.utilities.witer.HttpManager. Create a new HttpManager.java file in it. We make our HttpManager a singleton class for ease of access and use.

[sourcecode language="java"]
private static HttpManager mManager = null;
private static HttpClient mHttpClient = null;

private HttpManager(){
mHttpClient = new DefaultHttpClient();
}

public static HttpManager getInstance(){
if( mManager == null ){
mManager = new HttpManager();
}
return mManager;
}
[/sourcecode]

We create a public class that will be used to make the requests.

[sourcecode language="java"]
public void request(Context context, String url){

HttpQuery query = new HttpQuery(context, mHttpClient);
query.execute(url);
}
[/sourcecode]

Finally, here is the code for the core of the HttpManager – the HttpQuery. For now just look at the code inside the method doInBackground().

[sourcecode language="java"]
public class HttpQuery extends AsyncTask<String, String, Boolean>{

private Context mContext = null;
private HttpClient mClient = null;
private HttpGet mRequest = null;
private HttpResponse mResponse = null;

public HttpQuery( Context context, HttpClient client ) {
mContext = context;
mClient = client;
mRequest = new HttpGet();
}

@Override
protected Boolean doInBackground(String… url) {
try {
mRequest.setURI(new URI(url[0]));
mResponse = mClient.execute(mRequest);
Log.i(TAG, mResponse.getStatusLine().getReasonPhrase());
return true;
} catch (ClientProtocolException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (URISyntaxException e) {
Log.i(TAG, "Please check the Url!");
e.printStackTrace();
return false;
}
}

@Override
protected void onCancelled() {
// Covered in next post
}

@Override
protected void onPreExecute() {
// Covered in next post
}

@Override
protected void onPostExecute(Boolean result) {
// Covered in next post
}
}
[/sourcecode]

So we are basically creating a new HttpGet object in the constructor of the HttpQuery. We set the URI of the request object and use the client to execute the request. The result of the execute() is nothing but your http response. To make sure that we have got a valid response we print the Status Phrase of the response object using mResponse.getStatusLine().getReasonPhrase()

That’s it! 3 lines of code and you have your basic HttpManager ready. Now, to check that our HttpManager works properly, let us call it in the MainActivity. We have added a button in the MainActivity which invokes the HttpManager on click.

[sourcecode language="java"]
Button btnConvert = (Button)findViewById(R.id.btnConvert);
btnConvert.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
HttpManager.getInstance().request(MainActivity.this, "http://openexchangerates.org/latest.json");
}
});
[/sourcecode]

Before we can run the code and start receiving data, there is one final thing we must do. In your Android Manifest file, add the permission to access the internet

Final Review


Once you run the program and click on the button, you’ll observe the output in your LogCat. At the end of this tutorial, you have learnt how to,

  • Create a HttpManager and pass a request to it.

Here is the code for the HttpManager.

Android Tutorial – What Is The Exchange Rate [WITER]?

The Plan


It’s always fun to have something concrete at the end of a learning exercise. Its like a bonus. So I thought that the best way to explain a few important basic concepts which any android developer would require, was to make an application covering the topics. At the end of it, you would have learnt the concepts and would also have a working application :) So here goes…

Topics to be covered


  • Data access over http
  • AsyncTask
  • JSON Parsing

We will also go through ListView, ViewHolders and Application Context again. Just click on the links to go through tutorials covered previously.

The Project – WhatIsTheExchangeRate(WITER)


Its a currency converter based upon the current Forex rates. We get the Forex Rates from a free open source API available at . The information provided by the API is updated every hour and more details about it can be views at the link mentioned.

The user will be able to set his default currency from the settings page. Once set, all other currencies will be shown in terms of his set currency.

Plan of Action


Let us divide the project into chunks and then tackle one per post.

  1. A simple HttpManager with the Apache Http Client
  2. AsyncTask… What? Why? How?
  3. JSON parser in a jiffy
  4. Options Menu in Android
  5. ViewHolder! Make my ListView pretty

Our aim will be to have a running piece of code illustrating the functioning of the topic covered in each post, so that the code at the end of the post will be working code.

Let us begin by creating a new project called WhatIsTheExchangeRate, a package called com.utilities.witer and name your first activity as MainActivity.