Android JSON Parsing with Gson Tutorial
Apart
from XML, JSON is a very common format
used in API responses. Its simplicity has helped to gain quite the adoption in
favor of the more verbose XML. Additionally, JSON can easily be combined
with REST producing clear and easy
to use APIs. Android includes support for JSON in its SDK as someone can find
in the JSON package summary. However, using those classes,
a developer has to deal with low level JSON parsing, which in my opinion is
tedious and boring. For this reason, in this tutorial, I am going to show you
how to perform automatic JSON parsing.
For this purpose we are going to use the Google Gson library. From the official site:
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.
There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals.
Excellent, exactly what we need. Before delving into code, you might want to take a look at the Gson User Guide and bookmark the Gson API Javadocs. Let's get started by downloading Gson, with the current version being 1.6. We need the gson-1.6.jar from the distribution.
Add the Gson JAR to your project's classpath.
To illustrate how to use Gson for JSON parsing we are going to parse a JSON response from the Twitter API. Check the Twitter API Documentation for more info. We are going to use the Search API method for performing ad-hoc searches.
For example, for searching Twitter about Robin and retrieving the results in JSON format, here is the corresponding URL:
http://search.twitter.com/search.json?q=robin
This will give a one line JSON response containing all the relevant info. This one liner is quite hard to read, so a JSON editor would be quite handy. I use the Eclipse Json Editor plugin and works really well. Here is how the response looks formatted in my Eclipse IDE:
As you can see, we have a number of results and after that we have some other fields, such as “max_id”, “since_id”, “query” etc.
Thus, our main model object, named “SearchResponse” will be as follows:
For this purpose we are going to use the Google Gson library. From the official site:
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.
There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals.
Excellent, exactly what we need. Before delving into code, you might want to take a look at the Gson User Guide and bookmark the Gson API Javadocs. Let's get started by downloading Gson, with the current version being 1.6. We need the gson-1.6.jar from the distribution.
Add the Gson JAR to your project's classpath.
To illustrate how to use Gson for JSON parsing we are going to parse a JSON response from the Twitter API. Check the Twitter API Documentation for more info. We are going to use the Search API method for performing ad-hoc searches.
For example, for searching Twitter about Robin and retrieving the results in JSON format, here is the corresponding URL:
http://search.twitter.com/search.json?q=robin
This will give a one line JSON response containing all the relevant info. This one liner is quite hard to read, so a JSON editor would be quite handy. I use the Eclipse Json Editor plugin and works really well. Here is how the response looks formatted in my Eclipse IDE:
As you can see, we have a number of results and after that we have some other fields, such as “max_id”, “since_id”, “query” etc.
Thus, our main model object, named “SearchResponse” will be as follows:
01
|
package com.robin.android.json.model;
|
|
02
|
|
03
|
import java.util.List;
|
|
04
|
|
05
|
import com.google.gson.annotations.SerializedName;
|
|
06
|
|
07
|
public class SearchResponse
{
|
|
08
|
|
09
|
public List<Result>
results;
|
|
10
|
|
11
|
@SerializedName("max_id")
|
|
12
|
public long maxId;
|
13
|
|
|
14
|
@SerializedName("since_id")
|
15
|
public int sinceId;
|
|
16
|
|
17
|
@SerializedName("refresh_url")
|
|
18
|
public String
refreshUrl;
|
19
|
|
|
20
|
@SerializedName("next_page")
|
21
|
public String
nextPage;
|
|
22
|
|
23
|
@SerializedName("results_per_page")
|
|
24
|
public int resultsPerPage;
|
25
|
|
|
26
|
public int page;
|
27
|
|
|
28
|
@SerializedName("completed_in")
|
29
|
public double completedIn;
|
|
30
|
|
31
|
@SerializedName("since_id_str")
|
|
32
|
public String
sinceIdStr;
|
33
|
|
|
34
|
@SerializedName("max_id_str")
|
35
|
public String
maxIdStr;
|
|
36
|
|
37
|
public String
query;
|
|
38
|
|
39
|
}
|
We provide the various public fields (getter/setters with private fields can also be used) and in those case that the field name does not match the JSON response, we annotate with the SerializedName annotation.
Note that we also have a list of results, with the corresponding model class being:
01
|
package com.robin.android.json.model;
|
|
02
|
|
03
|
import com.google.gson.annotations.SerializedName;
|
|
04
|
|
05
|
public class Result
{
|
|
06
|
|
07
|
@SerializedName("from_user_id_str")
|
|
08
|
public String
fromUserIdStr;
|
09
|
|
|
10
|
@SerializedName("profile_image_url")
|
11
|
public String
profileImageUrl;
|
|
12
|
|
13
|
@SerializedName("created_at")
|
|
14
|
public String
createdAt;
|
15
|
|
|
16
|
@SerializedName("from_user")
|
17
|
public String
fromUser;
|
|
18
|
|
19
|
@SerializedName("id_str")
|
|
20
|
public String
idStr;
|
21
|
|
|
22
|
public Metadata
metadata;
|
23
|
|
|
24
|
@SerializedName("to_user_id")
|
25
|
public String
toUserId;
|
|
26
|
|
27
|
public String
text;
|
|
28
|
|
29
|
public long id;
|
|
30
|
|
31
|
@SerializedName("from_user_id")
|
|
32
|
public String
from_user_id;
|
33
|
|
|
34
|
@SerializedName("iso_language_code")
|
35
|
public String
isoLanguageCode;
|
|
36
|
|
37
|
@SerializedName("to_user_id_str")
|
|
38
|
public String
toUserIdStr;
|
39
|
|
|
40
|
public String
source;
|
41
|
|
|
42
|
}
|
Finally, we have one more class named “Metadata”:
01
|
package com.robin.android.json.model;
|
|
02
|
|
03
|
import com.google.gson.annotations.SerializedName;
|
|
04
|
|
05
|
public class Metadata
{
|
|
06
|
|
07
|
@SerializedName("result_type")
|
|
08
|
public String
resultType;
|
09
|
|
|
10
|
}
|
Let's now see how all these get wired using Gson. Here is our Activity:
01
|
package com.robin.android.json;
|
|
02
|
|
03
|
import java.io.IOException;
|
04
|
import java.io.InputStream;
|
05
|
import java.io.InputStreamReader;
|
|
06
|
import java.io.Reader;
|
07
|
import java.util.List;
|
|
08
|
|
09
|
import org.apache.http.HttpEntity;
|
|
10
|
import org.apache.http.HttpResponse;
|
11
|
import org.apache.http.HttpStatus;
|
|
12
|
import org.apache.http.client.methods.HttpGet;
|
13
|
import org.apache.http.impl.client.DefaultHttpClient;
|
|
14
|
|
15
|
import android.app.Activity;
|
|
16
|
import android.os.Bundle;
|
17
|
import android.util.Log;
|
|
18
|
import android.widget.Toast;
|
19
|
|
|
20
|
import com.google.gson.Gson;
|
21
|
import com.robin.android.json.model.Result;
|
|
22
|
import com.robin.android.json.model.SearchResponse;
|
23
|
|
|
24
|
public class JsonParsingActivity extends Activity
{
|
25
|
|
|
26
|
String
url = "http://search.twitter.com/search.json?q=robin";
|
27
|
|
|
28
|
@Override
|
29
|
public void onCreate(Bundle
savedInstanceState) {
|
|
30
|
|
31
|
super.onCreate(savedInstanceState);
|
|
32
|
setContentView(R.layout.main);
|
33
|
|
|
34
|
InputStream
source = retrieveStream(url);
|
35
|
|
|
36
|
Gson
gson = new Gson();
|
37
|
|
|
38
|
Reader
reader = new InputStreamReader(source);
|
39
|
|
|
40
|
SearchResponse
response = gson.fromJson(reader, SearchResponse.class);
|
41
|
|
|
42
|
Toast.makeText(this,
response.query, Toast.LENGTH_SHORT).show();
|
43
|
|
|
44
|
List<Result>
results = response.results;
|
45
|
|
|
46
|
for (Result
result : results) {
|
47
|
Toast.makeText(this,
result.fromUser, Toast.LENGTH_SHORT).show();
|
|
48
|
}
|
49
|
|
|
50
|
}
|
51
|
|
|
52
|
private InputStream
retrieveStream(String url) {
|
53
|
|
|
54
|
DefaultHttpClient
client = new DefaultHttpClient();
|
55
|
|
|
56
|
HttpGet
getRequest = new HttpGet(url);
|
57
|
|
|
58
|
try {
|
59
|
|
|
60
|
HttpResponse
getResponse = client.execute(getRequest);
|
61
|
final int statusCode
= getResponse.getStatusLine().getStatusCode();
|
|
62
|
|
63
|
if (statusCode
!= HttpStatus.SC_OK) {
|
|
64
|
Log.w(getClass().getSimpleName(),
|
65
|
"Error
" + statusCode + " for URL
" + url);
|
|
66
|
return null;
|
67
|
}
|
|
68
|
|
69
|
HttpEntity
getResponseEntity = getResponse.getEntity();
|
|
70
|
return getResponseEntity.getContent();
|
71
|
|
|
72
|
}
|
73
|
catch (IOException
e) {
|
|
74
|
getRequest.abort();
|
75
|
Log.w(getClass().getSimpleName(), "Error
for URL " + url, e);
|
|
76
|
}
|
77
|
|
|
78
|
return null;
|
79
|
|
|
80
|
}
|
81
|
|
|
82
|
}
|
First, we perform an HTTP GET request and retrieve the resource as a stream. We create a Gson instance and use it to perform the JSON parsing and retrieve our model object with all its fields populated.
Comments
Post a Comment