I'm relatively new to Java programming and need to parse a complex JSON object across the wire. I've been reading documentation on GSON the past day and Haven't had much luck being able to fully parse this type of structure:
{
'Events' : [{
'name' : 'exp',
'date' : '10-10-2010',
'tags' : ["tag 1", "tag2", "tag3"]
},...more events...],
'Contacts' : [{
'name' : 'John Smith',
'date' : '10-10-2010',
'tags' : ["tag 1", "tag2", "tag3"]
},...more contacts...],
}
I've been able to get it to work similarly to this question but can't figure out how to get that additional array level to work.
The correct way to do it using GSON in the format I'm looking for is:
//somewhere after the web response:
Gson gson = new Gson();
Event[] events = gson.fromJson(webServiceResponse, Event[].class);
//somewhere nested in the class:
static class Event{
String name;
String date;
public String getName()
{
return name;
}
public String getDate()
{
return date;
}
public void setName(String name)
{
this.name = name;
}
public void setDate(String date)
{
this.date = date;
}
}
Java has his own JSON parser: we can use it on Android as well.
Below you can find how you can get all events from your String.
String TAG = "JSON EXAMPLE";
String jsonString = "{\"Events\" : [{\"name\" : \"exp\",\"date\" : \"10-10-2010\",\"tags\" : [\"tag 1\",\"tag 2\",\"tag 3\"]}],\"Contacts\" : [{\"name\" : \"John Smith\",\"date\" : \"10-10-2010\",\"tags\" : [\"tag 1\",\"tag 2\",\"tag 3\"]}]}";
try {
JSONObject jsonObj = new JSONObject(jsonString); // create a json object from a string
JSONArray jsonEvents = jsonObj.getJSONArray("Events"); // get all events as json objects from Events array
for(int i = 0; i < jsonEvents.length(); i++){
JSONObject event = jsonEvents.getJSONObject(i); // create a single event jsonObject
Log.e(TAG, "Event name:" + event.getString("name") + " date: " + event.getString("date"));
JSONArray eventTags = event.getJSONArray("tags");
for(int j = 0; j < eventTags.length(); j++){
Log.e(TAG, "Event tag: " + eventTags.getString(j));
}
}
} catch (JSONException e) {
e.printStackTrace();
}
Be aware: Your JSON Object(from your question) will throw a exception because it is not valid( I'm not sure, but it look like a javascript object). You have to add some quotes to each property(key) and ecape them with \ (\").
This tool is really nice to test if a JSON String is valid or not.
Related
I have a nested JSON array from which I need to retrieve values of all Usernames nested within Friends.
{
"Friends": [
{"Username": "abc"},
{"Username": "xyz"}
]
}
After I get all the usernames, I want to store it in a List that I will use with an adapter and ListView.
FriendList.java:
public class FriendList
{
#SerializedName("Username")
private String username;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}
This is the code that I have written so far:
if (httpResult != null && !httpResult.isEmpty()) //POST API CALL
{
Type listType = new TypeToken<List<FriendList>>() {}.getType();
List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
FLCustomAdapter adapter = new FLCustomAdapter(getActivity(), friendList);
mainFriendsListView.setAdapter(adapter);
}
However, an error occurs: Failed to deserialize Json object.
Please suggest, what additions/changes should be made to it, so that I can retrieve nested JSON values into a list?
First of all, You have to understand the strucure of this Json.
You can see, it contains
1 . A json object
2 . This json object contains a json array which can include several different json objects or json arrays.
In this case, it contains json objects.
Parsing:
Get the Json Object first
try{
JSONObject jsonObject=new JSONObject(jsonResponse);
if(jsonObject!=null){
//get the json array
JSONArray jsonArray=jsonObject.getJSONArray("Friends");
if(jsonArray!=null){
ArrayList<FriendList> friendList=new ArrayList<FriendList>();
//iterate your json array
for(int i=0;i<jsonArray.length();i++){
JSONObject object=jsonArray.getJSONObject(i);
FriendList friend=new FriendList();
friend.setUserName(object.getString(Username));
friendList.add(friend);
}
}
}
}
catch(JSONException ex){
ex.printStackTrace();
}
hope, it will help you.
Solution with GSON.
You need to two class to parse this.
FriendList and UsernameDao.
public class UsernameDao {
#SerializedName("Username")
private String username;
//get set methods
}
Simple Json Parsing would be like this
JSONObject params=new JSONObject(httpResult);
JSONObject params1=params.getJsonObject("Friends");
JsonArray array=params1.getJsonArray();
for(int i=0;i<array.length();i++)
{
String userName=array.getJsonObject(i).getString("UserName");
// Do whatever you want to do with username
}
Following code works good without any use of GSON , Please try .
String jsonString = "Your Json Data";
JSONObject jsonRootObject = new JSONObject(jsonString );
JSONArray friendsArray = jsonRootObject .getJSONArray("Friends");
ArrayList<FriendList > friendsList = new ArrayList<FriendList >();
for(int friendsLen = 0 ;friendsLen < friendsArray .length() ; friendsLen ++){
FriendList userNameObj = new UserName();
JSONObject jsonObj = jsonRootObject.getJSONObject(friendsLen ) ;
String Username = jsonObj.getString("Username");
userNameObj .setUserName(Username );
friendsList .add(userNameObj );
}
Now friendsList the list which you want .
List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
This cannot work because it expects your whole JSON document to be just an array of FriendList element (by the way, why "FriendList"?): [{"Username": "abc"},{"Username": "xyz"}] -- this is what can be parsed by your approach.
The easiest solution to fix this (apart from harder to implement but more efficient streamed reading in order to peel of possible unnecessary properties) is just creating a correct mapping:
final class Wrapper {
#SerializedName("Friends")
final List<Friend> friends = null;
}
final class Friend {
#SerializedName("Username")
final String username = null;
}
Now deserialization is trivial and you don't have to define a type token because Gson has enough information for the type from the Wrapper.friends field:
final Wrapper wrapper = gson.fromJson(response, Wrapper.class);
for ( final Friend friend : wrapper.friends ) {
System.out.println(friend.username);
}
Output:
abc
xyz
Change List<FriendList> friendList = new Gson().fromJson(httpResult, listType);
to
FriendList friends = new Gson().fromJson(httpResult, listType);
List<Friend> friends = friends.list;
Updated FriendList.java as mentioned below
FriendList.java
public class FriendList
{
#SerializedName("Friends")
public List<Friend> list;
}
Friend.java
public class Friend
{
#SerializedName("Username")
private String username;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}
How to parse below Json Response with google Gson.?
{
"rootobject":[
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
},
{
"id":"7",
"name":"PP-1",
"subtitle":"name-I",
"key1":"punjab",
"key12":"2013",
"location":"",
"key13":"0",
"key14":"0",
"key15":"0",
"result_status":null
}
]
}
I'd create objects to "wrap" the response, such as:
public class Response {
#SerializedName("root_object")
private List<YourObject> rootObject;
//getter and setter
}
public class YourObject {
#SerializedName("id")
private String id;
#SerializedName("name")
private String name;
#SerializedName("subtitle")
private String subtitle;
//... other fields
//getters and setters
}
Note: use #SerializedName annotation to follow naming conventions in your Java attribute while matching the names in the JSON data.
Then you just parse the JSON with your Reponse object, like this:
String jsonString = "your json data...";
Gson gson = new Gson();
Response response = gson.fromJson(jsonString, Response.class);
Now you can access all the data in your Response object using getters and setters.
Note: your Response object may be used to parse different JSON responses. For example you could have JSON response that don't contain the id or the subtitle fields, but your Reponseobject will parse the response as well, and just put a null in this fields. This way you can use only one Responseclass to parse all the possible responses...
EDIT: I didn't realise the Android tag, I use this approach in a usual Java program, I'm not sure whether it's valid for Android...
You can try this hope this will work
// Getting Array
JSONArray contacts = json.getJSONArray("rootobject");
SampleClass[] sample=new SampleClass[contacts.length]();
// looping through All
for(int i = 0; i < contacts.length(); i++){
JSONObject c = contacts.getJSONObject(i);
// Storing each json item in variable
sample[i].id = c.getString("id");
sample[i].name = c.getString("name");
sample[i].email = c.getString("subtitle");
sample[i].address = c.getString("key1");
sample[i].gender = c.getString("key12");
sample[i].gender = c.getString("location");
sample[i].gender = c.getString("key13");
sample[i].gender = c.getString("key14");
sample[i].gender = c.getString("key15");
sample[i].gender = c.getString("result_status");
}
How can I parse this JSON using Gson?
I have an array with multiple object types and I don't know what kind of object I need to create to save this structure. I cannot change the json message (I don't control the server).
The only class that function (sort of) was this
public class Response {
private List<Object> tr;
private int results;
(...)
}
JSON Message (Note the array with multiple object types.)
{
"tr":
[
{
"a":
{
"userId": "112"
}
},
{
"b":
{
"userId": "123",
"address":"street dummy"
}
},
{
"a":
{
"userId": "154"
}
}
],
"results":3
}
The Gson User's Guide explicitly covers this:
https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Collection-with-Objects-of-Arbitrary-Types
You have an object with a field tr that is an array containing arbitrary types.
The users guide explains that you can't directly deserialize such a structure, and recomends:
Use Gson's parser API (low-level streaming parser or the DOM parser
JsonParser) to parse the array elements and then use Gson.fromJson()
on each of the array elements. This is the preferred approach.
In your case ... it would really depend on what objects were possible in that array. If they are all going to have that same inner object you'd want to do something like...
List<MyUserPojo> list = new ArrayList<MyUserPojo>();
JsonArray array = parser.parse(json).getAsJsonObject().getAsJsonArray("tr");
for (JsonElement je : array)
{
Set<Map.Entry<String,JsonElement>> set = je.getAsObject().entrySet();
JsonElement je2 = set.iterator().next().getValue();
MyUserPojo mup = new Gson().fromJson(je2, MyUserPojo.class);
list.add(mup);
}
And of course, this would need to be inside a custom deserializer for your actual object that would have the tr and results fields.
class MyPojo
{
List<MyUserPojo> userList;
int results;
}
class MyUserPojo
{
String userId;
String address;
}
class MyDeserializer implements JsonDeserializer<MyPojo>
{
#Override
public MyPojo deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
List<MyUserPojo> list = new ArrayList<MyUserPojo>();
JsonArray array = je.getAsJsonObject().getAsJsonArray("tr");
for (JsonElement je2 : array)
{
Set<Map.Entry<String,JsonElement>> set = je2.getAsObject().entrySet();
JsonElement je3 = set.iterator().next().getValue();
MyUserPojo mup = new Gson().fromJson(je3, MyUserPojo.class);
list.add(mup);
}
MyPojo mp = new MyPojo();
mp.tr = list;
mp.results = je.getAsObject().getAsJsonPrimitive("results").getAsInt();
return mp;
}
}
Now you're all set - you can use that deserializer and create your object:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyPojo.class, new MyDeserializer())
.build();
MyPojo mp = gson.fromJson(json, MyPojo.class);
If the a, b etc are important ... well, you'll have to figure that out. But the above should get you well on your way to understanding what's going to be needed to deal with your JSON structure.
For completeness sake, the only "hacky" way around this is if there is a fairly limited number of those types and the inner object also is fairly limited in terms of its fields. You could create a POJO that encompasses all the possibilities:
class MyPojo
{
MySecondPojo a;
MySecondPojo b;
...
MySecondPojo f;
}
class MySecondPojo
{
String userId;
String address;
...
String someOtherField;
}
When Gson deserializes JSON it will set any missing fields in your POJO(s) to null. You could now have tr be a List or array of these in your POJO. Again and to emphasize, this is really quite hacky and the wrong way to do it, but I thought I'd explain what would be required to directly parse that array.
I pick something from each answer and did it this way:
Response Object
public class Response {
private List<Users> tr;
private int results;
(...)
}
Generic User
public class User {
public static final int TYPE_USER_A =0;
public static final int TYPE_USER_B =1;
private String userId;
private int type;
(...)
}
A
public class a extends User {
private String location;
(...)
}
B
public class b extends User {
private String adress;
(...)
}
Parsing Method
private Response buildResponseObject(String response) {
Response tls = new Response();
List<Users> users = new ArrayList<users>();
User u;
try {
JSONObject object = new JSONObject(response);
tls.setResults(object.getInt("results"));
JSONArray array = object.getJSONArray("tr");
for (int i = 0; i < array.length(); i++) {
JSONObject trs = array.getJSONObject(i);
if (trs.has("a")) {
String json = trns.getString("a");
A a = new Gson().fromJson(json,A.class);
a.setType(User.TYPE_USER_A);
users.add(a);
} else if (trs.has("b")) {
String json = trs.getString("b");
B b= new Gson().fromJson(json,B.class);
B.setType(User.TYPE_USER_B);
users.add(b);
}
}
tls.setUsers(users);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tls;
}
This is not as elegant as I wanted and mix native JsonObjects with Gson methods but works for me.
Try this code here:
public class Address {
public String userId;
public String address;
// ...
}
public class Response {
private HashMap<String, Address> tr;
private int results;
// ...
}
Usage:
String json = "{\n \"tr\":\n {\n \"a\": {\n \"userId\": \"112\"\n },\n \"b\": {\n \"userId\": \"123\",\n \"address\":\"street dummy\"\n },\n \"c\": {\n \"userId\": \"154\"\n }\n },\n \"results\":3\n}";
Response users = new Gson().fromJson(json, Response.class);
As you may see I needed to modify the structure:
{
"tr":
{
"a": {
"userId": "112"
},
"b": {
"userId": "123",
"address":"street dummy"
},
"c": {
"userId": "154"
}
},
"results":3
}
But unfortunately I don't get it managed to allow multiple keys. Right now I have no idea how to fix this.
I think this link might help you:
https://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Examples
Basically, create a class for your "object" (kind of user I guess), and then use the deserialization code of Gson, like this:
Type collectionType = new TypeToken<Collection<User>>(){}.getType();
Collection<User> users= gson.fromJson(json, collectionType);
You can create corresponding java classes for the json objects. The integer, string values can be mapped as is. Json can be parsed like this-
Gson gson = new GsonBuilder().create();
Response r = gson.fromJson(jsonString, Response.class);
Here is an example- http://rowsandcolumns.blogspot.com/2013/02/url-encode-http-get-solr-request-and.html
I've a json output which returns something like this :
[
{
"title":"facebook",
"description":"social networking website",
"url":"http://www.facebook.com"
},
{
"title":"WoW",
"description":"game",
"url":"http://us.battle.net/wow/"
},
{
"title":"google",
"description":"search engine",
"url":"http://www.google.com"
}
]
I am familiar with parsing json having the title object, but i've no clue about how to parse the above json as it is missing the title object. Can you please provide me with some hints/examples so i can check them and work on parsing the above code?
Note : I've checked a similar example here but it doesn't have a satisfactory solution.
Your JSON is an array of objects.
The whole idea around Gson (and other JSON serialization/deserialization) libraries is that you wind up with your own POJOs in the end.
Here's how to create a POJO that represents the object contained in the array and get a List of them from that JSON:
public class App
{
public static void main( String[] args )
{
String json = "[{\"title\":\"facebook\",\"description\":\"social networking website\"," +
"\"url\":\"http://www.facebook.com\"},{\"title\":\"WoW\",\"description\":\"game\"," +
"\"url\":\"http://us.battle.net/wow/\"},{\"title\":\"google\",\"description\":\"search engine\"," +
"\"url\":\"http://www.google.com\"}]";
// The next 3 lines are all that is required to parse your JSON
// into a List of your POJO
Gson gson = new Gson();
Type type = new TypeToken<List<WebsiteInfo>>(){}.getType();
List<WebsiteInfo> list = gson.fromJson(json, type);
// Show that you have the contents as expected.
for (WebsiteInfo i : list)
{
System.out.println(i.title + " : " + i.description);
}
}
}
// Simple POJO just for demonstration. Normally
// these would be private with getters/setters
class WebsiteInfo
{
String title;
String description;
String url;
}
Output:
facebook : social networking website
WoW : game
google : search engine
Edit to add: Because the JSON is an array of things, the use of the TypeToken is required to get to a List because generics are involved. You could actually do the following without it:
WebsiteInfo[] array = new Gson().fromJson(json, WebsiteInfo[].class);
You now have an array of your WebsiteInfo objects from one line of code. That being said, using a generic Collection or List as demonstrated is far more flexible and generally recommended.
You can read more about this in the Gson users guide
JSONArray jsonArr = new JSONArray(jsonResponse);
for(int i=0;i<jsonArr.length();i++){
JSONObject e = jsonArr.getJSONObject(i);
String title = e.getString("title");
}
use JSONObject.has(String name) to check an key name exist in current json or not for example
JSONArray jsonArray = new JSONArray("json String");
for(int i = 0 ; i < jsonArray.length() ; i++) {
JSONObject jsonobj = jsonArray.getJSONObject(i);
String title ="";
if(jsonobj.has("title")){ // check if title exist in JSONObject
String title = jsonobj.getString("title"); // get title
}
else{
title="default value here";
}
}
JSONArray array = new JSONArray(yourJson);
for(int i = 0 ; i < array.lengh(); i++) {
JSONObject product = (JSONObject) array.get(i);
.....
}
i want to analyse the json just like:
[{"id":"ssq","name":"双色球","term":"2010092","date":"2010-08-12 19:15","numbers":{"normal":"3,13,19,27,28,30","special":"2"},"jackpot":"30000000"},{"id":"3d","name":"3D","term":"2010216","date":"2010-08-12 19:55","numbers":{"normal":"6,8,8"},"jackpot":"-"},{"id":"qlc","name":"七乐彩","term":"2010093","date":"2010-08-11 20:45","numbers":{"normal":"08,09,10,11,16,21,27","special":"26"},"jackpot":"0"},{"id":"dfljy","name":"东方6+1","term":"2010093","date":"2010-08-14 18:30","numbers":{"normal":"4,1,3,9,7,2","special":"羊"},"jackpot":"12866531"},{"id":"swxw","name":"15选5","term":"2010217","date":"2010-08-12 18:45","numbers":{"normal":"1,3,5,13,15"},"jackpot":"5693612"},{"id":"ssl","name":"时时乐","term":"20100811-23","date":"2010-08-12 10:27","numbers":{"normal":"6,7,1"},"jackpot":"-"},{"id":"klsf","name":"快乐十分","term":"201021649","date":"2010-08-11 22:00","numbers":{"normal":"5,11,12,14,20"},"jackpot":"-"},{"id":"klsc","name":"快乐双彩","term":"2010215","date":"2010-08-10 21:25","numbers":{"normal":"12,23,10,15,7,3","special":"11"} ,"jackpot":"198059"}]
i want to gain all of them,but the data is so many,so whether i need to create 8 kinds of class to store the data,so to be easier to use.thanks!
To add to cfei's response, one thing that I've done when processing JSON responses from Flickr, is create a new class particularly for that type of object.
So for yours, just playing it by ear, something like the below:
public class Lottery() {
private JSONObject json;
private String id;
private String name;
private String term;
private String date;
private String norm_numbers;
private String spec_numbers;
private String jackpot;
public Lottery(JSONObject json) {
this.json = json;
}
public void setId()
{
try {
id = json.getString("id");
} catch (JSONException e) {
id = "";
}
}
//additional getters and setters, etc.
}
This way, you can make an array of objects, and access the fields like so:
//...get a JSONObject from the array...
Lottery lottery = new Lottery(json);
Log.v("ID", lottery.id);
Log.v("Name", lottery.name);
and so on.
Do you mean that you want to iterate through each of the eight JSONObjects in this JSONArray? You need to create a JSONArray object with the input string you posed above (let's call it "response", as used below) and then iterate through the array to get each JSONObject it contains. For example:
JSONArray array = new JSONArray(response);
for(int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
// do something with obj
// example: to get the id for a particular object, use obj.getString("id")
Log.i("Example", "the id is"+obj.getString("id"));
}