Reading JSON data using GSON - android

I spent the past 4 hours looking at various answers and other resources but I simply can't wrap my head around JSON parsing. I need some help.
Here is the JSON string:
{
"success": true,
"categories": [
{
"category_id": "20",
"parent_id": "0",
"name": "Desktops",
"image": "***",
"href": "***",
"categories": null
},
{
"category_id": "25",
"parent_id": "0",
"name": "Components",
"image": "***",
"href": "***",
"categories": null
},
{
"category_id": "34",
"parent_id": "0",
"name": "MP3 Players",
"image": "***",
"href": "***",
"categories": null
}
]
}
Here is my Data class:
public class Data
{
String success;
List<Category> categories;
// Various get/set functions and a toString override
public class Category
{
String category_id;
String name;
String image;
// Various get/set functions
}
}
Here is where I'm trying to read this:
private class GetJson extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params)
{
String results = "Fail";
URL url = null;
try
{
url = new URL("***");
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
URLConnection ucon = null;
try
{
ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(is));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
{
result += line;
}
Data data = new Gson().fromJson(result, Data.class);
result = data.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
return results;
}
protected void onPostExecute(String result)
{
Toast.makeText(con, result, Toast.LENGTH_SHORT);
}
}
I'm not getting anything on the stacktrace at all. I checked ADB several times. Everything seems to be working but I get no Toast or error message.
What am I doing wrong?

you forgot to show your Toast
try this
Toast.makeText(con, result, Toast.LENGTH_SHORT).show();
lol
and further
Data data = new Gson().fromJson(result, Data.class);
result = data.toString();
return result; // need return this
otherwise will always get "Fail"

//First generate getter setter of data class variables.
TypeToken<Data> tokenPoint1 = new TypeToken<Data>() {};
//SYSO result string here for Confirmation
Gson gson = new Gson();
Data dataobj= gson.fromJson(result, tokenPoint1.getType());
// syso dataobj.getname();
//Hope this will work for you

Related

Pull JSONObject from JSONArray?

I'm trying to pull the "price" object from the "current" array, I have been at it for hours now with no luck, any help is appreciated! :)
try {
URL url = new URL("http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=2");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
} finally {
JSONArray nu1 = jobj.getJSONArray("current");
JSONObject jobj = nu1.getJSONObject(0);
String price = jobj.getString("price");
Toast.makeText(getApplicationContext(), price, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e("ERROR", e.getMessage(), e);
return null;
}
}
protected void onPostExecute(String response) {
}
}
}
I tried to get response from your URL. here is the response :
{
"item": {
"icon": "http://services.runescape.com/m=itemdb_rs/1502782993572_obj_sprite.gif?id=2",
"icon_large": "http://services.runescape.com/m=itemdb_rs/1502782993572_obj_big.gif?id=2",
"id": 2,
"type": "Ammo",
"typeIcon": "http://www.runescape.com/img/categories/Ammo",
"name": "Cannonball",
"description": "Ammo for the Dwarf Cannon.",
"current": {
"trend": "neutral",
"price": 339
},
"today": {
"trend": "positive",
"price": "+1"
},
"members": "true",
"day30": {
"trend": "positive",
"change": "+1.0%"
},
"day90": {
"trend": "negative",
"change": "-11.0%"
},
"day180": {
"trend": "negative",
"change": "-21.0%"
}
}
}
there is no array in the response.
Edit:
assume that you store your response in a String named response, you can get price, using the following code:
JSONObject json = new JSONObject(response);
JSONObject item = json.getJSONObject("item");
JSONObject current = item.getJSONObject("current");
int price = current.getInt("price");
Edit2: use
String response = stringBuilder.toString();
and then make a JSONObject from 'response' .

my PostExecute doesn't execute in my Async

I'm trying to read data from this API: http://events.makeable.dk/api/getEvents with the AsyncTask method which Is first time I try this. I'm trying to only read all TITLES from the API, but I'm not getting any titles.
Instead I get this exception: W/System.err: org.json.JSONException: (...)
Which shows me the whole API.
I have put Log.d(); around my code and I can se that my code never do or reach something in onPostExecute(String s) and thats is maybe why I never get any TITLES.
The many examples on the web of how to do this is so different from eachother and makes this very frustrating to solve!
private class JsonParser extends AsyncTask<String, Void, String> {
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "LOADING DATA FROM API", Toast.LENGTH_SHORT).show();
}
#Override
protected String doInBackground(String... params) {
try{
url = new URL(URL);
conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStream inputStream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine())!= null){
result.append(line);
}
return (result.toString());
}
}catch (MalformedURLException e){
e.printStackTrace();
}catch (Exception ee){
ee.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String s) {
//------ never comes below this area //-----------
try{
JSONArray jsonArray = new JSONArray(s);
for(int i =0; i<jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
Log.d("TAG", "JSON: " + jsonObject.getString("TITLE"));
}
}catch (Exception e){
e.printStackTrace();
}
}
}
I viewed your API's response at this Website. It is a JSON Object because it is started by an open curly brace {. So therefore use JSONObject first.
The response looks like this:
{
"success": true,
"message": "548 events returned successfully",
"last_change": 1459515263,
"events": [
{
"category": "Musik",
"category_id": "75",
"datelist": [
{
"start": 1436536800,
"end": 1436544000
}
],
"description": "",
"description_english": "",
"description_german": "",
"eventgroup": "",
"eventid": "55815f7fe714a",
"family_friendly": "0",
"last_updated": 1436166668,
"location_address": "Klostertorv 1",
"location_city": "Århus C",
"location_id": "1593",
"location_latitude": 56.158092,
"location_longitude": 10.206756,
"location_name": "Klostertorv",
"location_postcode": "8000",
"organizer_email": "",
"organizer_name": "Café Smagløs ",
"organizer_phone": "",
"picture_name": "http://www.jazzfest.dk/img/photos_big/tcha-badjo---strings-og-buttons.jpg",
"price": "-1",
"subcategory": "Musik",
"subcategory_id": "84",
"subtitle": "",
"subtitle_english": "",
"subtitle_german": "",
"tags": "Swing/Mainstream",
"tickets_url": "",
"title": "Tcha Badjo + Strings & Buttons KONCERT AFLYST",
"title_english": "Tcha Badjo + Strings & Buttons CONCERT CANCELLED",
"title_german": "Tcha Badjo + Strings & Buttons CONCERT CANCELLED",
"url": "http://www.jazzfest.dk/?a=reviews&lang=&kryds_id=2122&y=2015",
"user_id": "23",
"video_url": ""
}]
}
So therefore it is:
try {
JSONObject object = new JSONObject(s);
JSONArray events = object.getJSONArray("events");
int evSize = events.length();
for (int x = 0; x < evSize; x++) {
JSONObject object1 = events.getJSONObject(x);
String title = object1.getString("title");
}
} catch (JSONException e) {
e.printStackTrace();
}

Retrofit error: Expected BEGIN_ARRAY but was STRING

In api response sometimes It can be array, sometimes it can be string.
Here details is Array
{ "ts": "2015-06-16 11:28:33","success": true,"error": false,"details": [
{
"user_id": "563",
"firstname": "K.Mathan"
},
{
"user_id": "566",
"firstname": "Surya"
},
{
"user_id": "562",
"firstname": "Idaya"
} ]}
Sometimes details can be string
{ "ts": "2015-06-16 11:28:33",
"success": true,
"error": false,
"details": "no data" }
Here details is String
How to get value from this type of response
My current declaration is
#SerializedName(value="details")
public List<detailslist> details ;
Anyone please help me to find the solution?
Did you try with the raw response type?
#GET("your_url")
void getDetails(Callback<Response> cb);
Then you can parse the Response using JSONObject and JSONArray like this:
Callback<Response> callback = new Callback<Response>() {
#Override
public void success(Response detailsResponse, Response response2) {
String detailsString = getStringFromRetrofitResponse(detailsResponse);
try {
JSONObject object = new JSONObject(detailsString);
//In here you can check if the "details" key returns a JSONArray or a String
} catch (JSONException e) {
}
}
#Override
public void failure(RetrofitError error) {
});
Where the getStringFromRetrofitRespone could be:
public static String getStringFromRetrofitResponse(Response response) {
//Try to get response body
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(response.getBody().in()));
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
I guess you can write your own deserializer to use in retrofit but it also works with just inferring that it's an object and then handle it later in your code.
#SerializedName(value="details")
public Object details;

Trying to Parse Instagram JSON

My app is crashing when trying to parse Instagram JSON. What am I doing wrong here?
public class InstagramActivity extends BaseActivity {
static String url;
static ArrayList<String> thumbnailURLS;
static ArrayList<String> standardURLS;
static Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grid);
context = getApplicationContext();
getActionBar().setTitle("Instagram");
url = "https://api.instagram.com/v1/users/1373666362/media/recent/?client_id=a2b04732b52d43c99fe453a8ca2a5512&count=50";
thumbnailURLS = new ArrayList<String>();
standardURLS = new ArrayList<String>();
new ParseJSON().execute();
}
public static class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser()
{
}
public JSONObject getJSONFromUrl(String jsonUrl)
{
// Making HTTP request
try
{
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(jsonUrl);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
json = sb.toString();
}
catch (Exception e)
{
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try to parse the string to a JSON object
try
{
jObj = new JSONObject(json);
}
catch (JSONException e)
{
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
public static class ParseJSON extends AsyncTask<Void,Void,ArrayList> {
#Override
protected void onPreExecute()
{
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected ArrayList doInBackground(Void... params) {
JSONParser jParser = new JSONParser();
// get json from url here
JSONObject json = jParser.getJSONFromUrl(url);
try {
JSONArray dataArray = json.getJSONArray("data");
int thumbnailsCount = dataArray.length();
for (int i = 0; i < thumbnailsCount; i++) {
JSONObject imagesObject = dataArray.getJSONObject(i).getJSONObject("images");
String thumbURL = imagesObject.getJSONObject("thumbnail").getString("url");
thumbnailURLS.add(thumbURL);
}
}
catch (Exception e) {
e.getMessage().toString();
}
return thumbnailURLS;
}
#Override
protected void onPostExecute(ArrayList result) {
super.onPostExecute(result);
for (String thumb : thumbnailURLS) {
System.out.println(thumb);
}
}
}
}
It catches a JSONException
E/JSON Parser﹕ Error parsing data org.json.JSONException: End of input at character 0 of
and
E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #2
This is NULL. JSONObject json = jParser.getJSONFromUrl(url);
Here is some of the expected JSON.
{
"pagination": {
"next_url": "https://api.instagram.com/v1/users/1373666362/media/recent?access_token=25320296.1fb234f.b797e861c2494059b6584ac9749208fe&count=2&max_id=791341826737262101_1373666362",
"next_max_id": "791341826737262101_1373666362"
},
"meta": {
"code": 200
},
"data": [
{
"attribution": null,
"tags": [
"kystatefair"
],
"type": "image",
"location": null,
"comments": {
"count": 0,
"data": []
},
"filter": "Amaro",
"created_time": "1408648864",
"link": "http://instagram.com/p/r-MuYWFU96/",
"likes": {
"count": 5,
"data": [
{
"username": "tayworthington_",
"profile_picture": "http://photos-g.ak.instagram.com/hphotos-ak-xaf1/10632550_835588266460870_765781001_a.jpg",
"id": "24471760",
"full_name": "τᎯϓιΘર"
},
{
"username": "renee_laurent",
"profile_picture": "http://images.ak.instagram.com/profiles/profile_407687505_75sq_1397913189.jpg",
"id": "407687505",
"full_name": "Renee Laurent"
},
{
"username": "kystatefair",
"profile_picture": "http://images.ak.instagram.com/profiles/profile_381460857_75sq_1396983015.jpg",
"id": "381460857",
"full_name": "kystatefair"
},
{
"username": "jennaharrod1",
"profile_picture": "http://photos-b.ak.instagram.com/hphotos-ak-xfa1/10665605_1495839117327497_809128971_a.jpg",
"id": "18591399",
"full_name": "Jenna Harrod"
}
]
},
"images": {
"low_resolution": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598650_352432021574566_306460147_a.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598650_352432021574566_306460147_s.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598650_352432021574566_306460147_n.jpg",
"width": 640,
"height": 640
}
},
"users_in_photo": [],
"caption": {
"created_time": "1408648864",
"text": "Congratulations to The Lindsey Family for winning the Gospel Quartet competition! #kystatefair",
"from": {
"username": "kyfarmbureau",
"profile_picture": "http://photos-b.ak.instagram.com/hphotos-ak-xpf1/10349740_650479825030913_1755233568_a.jpg",
"id": "1373666362",
"full_name": "Kentucky Farm Bureau"
},
"id": "792126548887293629"
},
"user_has_liked": false,
"id": "792126548258148218_1373666362",
"user": {
"username": "kyfarmbureau",
"website": "",
"profile_picture": "http://photos-b.ak.instagram.com/hphotos-ak-xpf1/10349740_650479825030913_1755233568_a.jpg",
"full_name": "Kentucky Farm Bureau",
"bio": "",
"id": "1373666362"
}
},
{
"attribution": null,
"tags": [
"kfbmtc"
],
"type": "image",
"location": null,
"comments": {
"count": 0,
"data": []
},
"filter": "Normal",
"created_time": "1408555318",
"link": "http://instagram.com/p/r7aTLelU4V/",
"likes": {
"count": 4,
"data": [
{
"username": "corkey_cole",
"profile_picture": "http://photos-e.ak.instagram.com/hphotos-ak-xaf1/10598220_490230854445140_2139881142_a.jpg",
"id": "324166968",
"full_name": "corkey_cole"
},
{
"username": "renee_laurent",
"profile_picture": "http://images.ak.instagram.com/profiles/profile_407687505_75sq_1397913189.jpg",
"id": "407687505",
"full_name": "Renee Laurent"
},
{
"username": "silveradomafia04",
"profile_picture": "http://photos-e.ak.instagram.com/hphotos-ak-xfa1/914483_1500860143488988_1771984176_a.jpg",
"id": "1006562558",
"full_name": "Gideon Bailey"
},
{
"username": "sharelouisville",
"profile_picture": "http://images.ak.instagram.com/profiles/profile_1302605134_75sq_1399019203.jpg",
"id": "1302605134",
"full_name": "Share Louisville"
}
]
},
"images": {
"low_resolution": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598436_1456586981280578_133918080_a.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598436_1456586981280578_133918080_s.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://scontent-a.cdninstagram.com/hphotos-xaf1/t51.2885-15/10598436_1456586981280578_133918080_n.jpg",
"width": 640,
"height": 640
}
},
"users_in_photo": [],
"caption": {
"created_time": "1408555318",
"text": "Media is starting to crowd around for #kfbmtc",
"from": {
"username": "kyfarmbureau",
"profile_picture": "http://photos-b.ak.instagram.com/hphotos-ak-xpf1/10349740_650479825030913_1755233568_a.jpg",
"id": "1373666362",
"full_name": "Kentucky Farm Bureau"
},
"id": "791341827391573199"
},
"user_has_liked": false,
"id": "791341826737262101_1373666362",
"user": {
"username": "kyfarmbureau",
"website": "",
"profile_picture": "http://photos-b.ak.instagram.com/hphotos-ak-xpf1/10349740_650479825030913_1755233568_a.jpg",
"full_name": "Kentucky Farm Bureau",
"bio": "",
"id": "1373666362"
}
}
]
}
UPDATE: The problem appears to be with the Instagram api url I'm using isn't giving me the JSON. I think it may be because I'm using my client_id instead of getting an access token. Does anyone know if that is the case? I used a JSON URL from something else that I know doesn't require an access token and it returned the JSON just fine.
I have updated your method getJSONFromUrl, which can be seen below:
The problem is that, the server is returning 405 means method not allowed. You was using POST to access the data, which this server does not allow. You have to use GET here for a successful request.
Rest of your code is working fine.
You can update the code below to add a default case where you can return a valid constant json string with a message that can avoid app crash, as well you can add other cases like 404 and 405 and return a valid json with an appropriate message that is suitable to the user to understand.
public JSONObject getJSONFromUrl(String jsonUrl)
{
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(jsonUrl);
String responseBody = "DEFAULT_MSG_TEXT";
int resCode = 0;
try{
HttpResponse response = client.execute(get);
int responseCode = response.getStatusLine().getStatusCode();
resCode = responseCode;
switch(responseCode) {
case 200:
HttpEntity entity = response.getEntity();
if(entity != null) {
responseBody = EntityUtils.toString(entity);
}
break;
}
}
catch(Exception ex){
Log.e("Post Error",resCode + "\n Exception" + ex);
responseBody = "DEFAULT_MSG_TEXT";
}
json = responseBody;
// try to parse the string to a JSON object
try
{
jObj = new JSONObject(json);
}
catch (JSONException e)
{
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
Try this and let me know !!!

Android: JSONObject only parses the final object in file

I have a json file formatted like this (only the actual file has no whitespace):
{
"main": [
{
"sections": [
"sec1",
"sec2"
],
"title": "Section List 1"
},
{
"sections": [
"sec3",
"sec4",
"sec5"
],
"title": "Section List 2"
}
],
"sections": {
"sec1": {
"products": [
"prod1",
"prod2"
]
},
"sec2": {
"products": [
"prod3"
]
}
},
"products": {
"prod1": {
"url": "url1.gif",
"title": "Product 1"
},
"prod2": {
"url": "url2.gif",
"title": "Product 2"
},
"prod3": {
"url": "url3.gif",
"title": "Product 3"
}
}
}
When I attempt to send the data for that file into JSONObject, the JSONObject being loaded only contains the final object in the top list, in this case "products". Right now, my code to load the JSONObject is this:
JSONObject dlResult = new JSONObject(new Scanner(cnxn.getInputStream()).nextLine());
I've also tried storing the data in a String first and giving that to the JSONObject constructor, I've tried giving that String to a JSONTokener first, and giving that tokener to the JSONObject constructor. Both the String and the JSONTokener contain the entire file, but once it gets put into the JSONObject, it's always the same thing - "main" and "sections" get cut out, and only "products" remains.
Here's the rest of my relevant code:
public class MapsListFragment extends ListFragment
{
private static JSONObject mDlResult;
private ArrayAdapter<MapInfo> mMapListAdapter = null;
private class MapInfo
{
private String mText;
private String mURL;
MapInfo(String inText, String inURL)
{
mText = inText;
mURL = inURL;
}
public String URL()
{
return mURL;
}
#Override
public String toString()
{
return mText;
}
}
public class MapsListUpdater extends AsyncTask<String, String, JSONObject>
{
private static final String URL = "http://jsonURL/products.json";
private Date lastUpdate;
#Override
protected JSONObject doInBackground(String... inObjects)
{
Date ifModifiedSince = lastUpdate;
try
{
HttpURLConnection cnxn = (HttpURLConnection) new URL(URL).openConnection();
if (ifModifiedSince != null)
cnxn.setIfModifiedSince(ifModifiedSince.getTime());
cnxn.connect();
if (cnxn.getResponseCode() != HttpURLConnection.HTTP_NOT_MODIFIED)
{
mDlResult = new JSONObject(new Scanner(cnxn.getInputStream()).nextLine());
}
cnxn.disconnect();
}
catch (Exception e)
{
boolean check = true;
}
return mDlResult;
}
#Override
protected void onPostExecute(JSONObject result)
{
super.onPostExecute(result);
try
{
// This is really ugly and brute-forcey, but it's the only way I could get JSONObjects populated with ALL the data!
/*String[] tryThis = mDlResult.split(",\"sections\":");
tryThis[0] += '}';
tryThis[1] = tryThis[1].substring(0, tryThis[1].indexOf("]}},\"products\":"));
tryThis[1] = "{\"sections\":" + tryThis[1] + "]}}}";*/
JSONObject mainObj = mDlResult.getJSONObject("main");//new JSONObject(mDlResult);
JSONArray mainArray = mainObj.getJSONArray("main");
Vector<String> titles = new Vector<String>();
mMapListAdapter.clear();
for (int i = 0; i < mainArray.length(); i++)
{
JSONObject object = mainArray.getJSONObject(i);
String title = object.getString("title");
if(!titles.contains(title))
{
titles.add(title);
mMapListAdapter.add(new MapInfo(object.getString("title"), null));
}
}
}
catch (Exception e)
{
boolean check = true;
}
}
}
}
I feel a little foolish now. As it turns out, the JSONObject was getting EXACTLY what I asked it for... only the objects within it were getting reordered, so I couldn't see the first 2 objects in my debugger!
Try reading it into a JSONArray and let me know how you get on:
JSONArray dlResult = new JSONArray(cnxn.getInputStream());

Categories

Resources