How to handle JSON that contains strings with bracket? - android

I'm creating an activity that get a JSON file from internet (via AsyncTask).
I'm experiencing this error: org.json.JSONException: Unterminated string at character...
I checked the JSON file that I downloaded inside the app and I discovered that there is an object that contains brackets. Here is the suspected JSON object:
[{ ... }{"id":"5674563646","cat":"Uncategorized","subcat":"Uncategorized","name":"Tecno Lab","desc":"We run open hours from 8-10pm and [most] Saturdays from 12-6pm.","addr":"Main Street","city":"New York","country":"United States"}
{ ... }]
So, how to escape the brackets from my activity?
Here is the part of AsyncTask in which I download the JSON file:
protected String doInBackground(String... urls) {
int timeout = 10;
int i, count = 0;
BasicHttpParams basicParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(basicParams, timeout * 1000);
HttpConnectionParams.setSoTimeout(basicParams, timeout * 1000 );
DefaultHttpClient client = new DefaultHttpClient(basicParams);
StringBuilder stringBuilder = new StringBuilder();
for (i = 0; i < urls.length; i++) {
HttpGet request = new HttpGet(urls[i]);
request.addHeader("Cache-Control", "no-cache");
try {
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
InputStreamReader in = new InputStreamReader(entity.getContent());
BufferedReader reader = new BufferedReader(in);
String line = "";
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
count++;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
publishProgress(count * 100 / urls.length);
}
return stringBuilder.toString();
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
...
JSONArray ja = new JSONArray(result);
...

JSON response normally contains two kinds of brackets {} and [] but both the brackets have quite different meaning and use. While, the first one represents JSON Object, the second one represents JSON Array.
In the JSON file you downloaded, the problem has nothing to do with the [most] word as it is inside double quotes. The problem in your JSON input is "addr": "Main Street". The opening double quote is missing there.
Corrected JSON input:
{"id":"5674563646","cat":"Uncategorized","subcat":"Uncategorized","name":"Tecno Lab","desc":"We run open hours from 8-10pm and [most] Saturdays from 12-6pm.","addr":"Main Street","city":"New York","country":"United States"}

Related

How to handle 500 Internal Server Error when using JSON

I am relatively new to Android and I am using JSON to get data from a server. On the first loop at line 22, the StringBuilder contains, 500 Internal Server Error and then the jArray ends up coming back null. How can I handle this error?
public static JSONObject getJSON() {
String jsonString = "";
InputStream inStream = null;
//http post
JSONObject jArray = null;
try {
HttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httpPost = new HttpPost(WS_URL);
httpPost.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
inStream = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
inStream.close();
jsonString = sb.toString();
jArray = new JSONObject(jsonString);
//outputTransactions(jArray);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return jArray;
}
Though its a late reply but it might help others. You need to check the response status from the server before parsing it as JSON.
For ex.
int status_code=response.getStatusLine().getStatusCode();
if(status_code!=200){
Log.d("MYLOG","ERROR! Response status is"+status_code);
}
else{
inStream = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
inStream.close();
// Rest of your code......
}
or Optionally you can check the status code and display the error to the user
Like:
else if(status_code==404){
Log.d("MYLOG","Sorry! Page not found! Check the URL ");
}else if(status_code==500){
Log.d("MYLOG","Server is not responding! Sorry try again later..");
}
Hope it helps for newbies like you :-)
A "500 Internal Server" error means the server had a problem responding to your request. You are not getting a JSON string response.
Then when you try to create your jArray, the string is not valid JSON and the JSONObject cannot parse it - it returns "null" as you say.
You can parse the server response to see if it contains this string, and then create whatever jArray object you want, but you can't get a JSON object from a non-JSON string.
Take a look at this answer: https://stackoverflow.com/a/8148785/1974614
You should check the statusCode against 500
You should consider use a library to handle the REST requests like: http://square.github.io/retrofit/
If you use a library like that you can get an object from json when a success response is available and other when an error occur.
MyApi mylogin = restAdapter.create(MyApi.class); //this is how retrofit create your api
mylogin.login(username,password,new Callback<String>() {
#Override
public void success(String s, Response response) {
//process your response if login successfull you can call Intent and launch your main activity
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace(); //to see if you have errors
}
});
}
I got the same problem like you and I solved it because I missed a part while adding GSON .jar files to adding my serverside project. I think you should carrefully add external libraries to your project too like me.With these links I could aware of problem .
LINK 1
LINK 2

Cannot receive utf-8 characters by json to Android

I'm building a simple Android application that sends items by json to a python web service for storage in a sqlite database. This part works fine and when recalled the items have their correct 'åäö' characters.
When I put these items in a json to return to the application (using code below) I'm not so sure any more. Instead of 'ö' I get '\xc3\xb6', which I believe would be the utf-8 representation?
connection = sqlite3.connect('database.db')
connection.text_factory = str
cursor = connection.cursor()
cursor.execute("SELECT item, number FROM Items")
rows = cursor.fetchall()
jsobj = []
for row in rows:
jsobj.append({'number':row[1], 'item':row[0]})
When I parse the json object in my app I'm not able to turn the '\xc3\xb6' back into 'ö'
This is the Android code at work:
HttpClient client = new DefaultHttpClient();
HttpGet post = new HttpGet(super.url);
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content, "UTF-8"));
JSONArray itemsOnServer = new JSONArray();
itemsOnServer = new JSONArray(reader.readLine());
return itemsOnServer;
Result sent into another function:
ArrayList<Vara> varor = new ArrayList<Vara>();
String vara = "";
int antal;
for (int i = 0; i < json.length(); i++) {
JSONObject object;
try {
object = json.getJSONObject(i);
try {
try {
vara = new String(object.getString("vara").getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} System.out.println(vara);
antal = object.getInt("antal");
varor.add(new Vara(vara, antal));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return varor;
Everything works fine except the special characters. Please help, I'm going nuts.
b'\xc3\xb6' is a bytestring that can be decoded into Unicode string that contains a single U+00f6 LATIN SMALL LETTER O WITH DIAERESIS Unicode codepoint:
>>> b'\xc3\xb6'.decode('utf-8')
u'\xf6'
By default text_factory is set to unicode for sqlite3 i.e., you should receive Unicode string for TEXT objects if you remove connection.text_factory = str from your code.

how get return value from node js to android?

I create android apps as client and node as server, i got problem when i request value from android to node, i use this code in android to communicate with node js
String xResult = getRequestJSON("http://mydomain.com:8888");
public String getRequestJSON(String Url){
String sret="";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(Url);
try{
HttpResponse response = client.execute(request);
sret =requestJSON(response);
}catch(Exception ex){
}
return sret;
}
public static String requestJSON(HttpResponse response){
String result = "";
try{
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null){
str.append(line + "\n");
}
in.close();
result = str.toString();
}catch(Exception ex){
result = "Error";
}
return result;
}
and i got result like this in node.
[{"posid":"P0S6f50b314b2c279a2083cb0ef821ccb4d20140218120720","id_a":"ltv#ltv.com","gambar_a":"6f50b314b2c279a2083cb0ef821ccb4d.jpg","user":"lutfi soe","pwaktu":"2014-02-18T05:07:20.000Z","posnya":"test dr android","plat":-7.983757710988161,"plong":112.6549243927002,"pjenis":"I","vote":0}]
my question is,how i receive json like that in android ?and parse to string?
thanks
If you are receiving Json string in proper format then you can use JSON jar to parse this json.
You can get a tutorial for JSON parsing here
I think your question is more on how to parse and access the result in java[read Android].
Here is a solution that could help JavaScript type arrays in JAVA
JsonArray yourArray = new JsonParser()
.parse("[[\"2012-14-03\", 2]]")
.getAsJsonArray();
// Access your array like so - yourArray.get(0).getAsString();
// yourArray.get(0).getAsInt() etc
The above is using a library called Gson
P.S: I just plagiarized my own answer. Not sure what criteria to use to mark this question as a duplicate

android HttpGet incomplete response BufferedReader

Im doing a simple http get,
I see on my result an incomplete response,
what Im doing wrong?
here the code:
class GetDocuments extends AsyncTask<URL, Void, Void> {
#Override
protected Void doInBackground(URL... urls) {
Log.d("mensa", "bajando");
//place proper url
connect(urls);
return null;
}
public static void connect(URL[] urls)
{
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet("http://tiks.document.dev.chocolatecoded.com.au/documents/api/get?type=tree");
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Examine the response status
Log.d("mensa",response.getStatusLine().toString());
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
// now you have the string representation of the HTML request
Log.d("mensa", "estratagema :: "+result);
JSONObject jObject = new JSONObject(result);
Log.d("mensa", "resposta jObject::"+jObject);
Log.d("mensa", "alive 1");
JSONArray contacts = null;
contacts = jObject.getJSONArray("success");
Log.d("mensa", "resposta jObject::"+contacts);
Log.d("mensa", "alive");
//instream.close();
}
} catch (Exception e) {}
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
Log.d("mensa", "linea ::"+line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
i call it with:
GetDocuments get = new GetDocuments();
URL url = null;
try {
url = new URL("ftp://mirror.csclub.uwaterloo.ca/index.html");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//URL url = new URL("http://www.google.es");
get.execute(url);
edit 1
I refer to incomplete as the response that gets truncated?
please notice in below image of response how string gets truncated,
is this because of the log size?,
but the other problem is that it doesn't parse?
thanks!
I don't know if this is going to resolve your problem but you can get rid of your method and use simply:
String responseString = EntityUtils.toString(response.getEntity());
I've had exactly the same issue for the last couple of days. I found that my code worked over WiFi but not 3G. In other words I eliminated all the usual threading candidates. I also found that when I ran the code in the debugger and just waited for (say) 10 seconds after client.execute(...) it worked.
My guess is that
response = httpclient.execute(httpget);
is an asynchronous call in itself and when it's slow returns a partial result... hence JSON deserialization goes wrong.
Instead I tried this version of execute with a callback...
try {
BasicResponseHandler responseHandler = new BasicResponseHandler();
String json = httpclient.execute(httpget, responseHandler);
} finally {
httpclient.close();
}
And suddenly it all works. If you don't want a string, or want your own code then have a look at the ResponseHandler interface. Hope that helps.
I have confirmed that this is because size limit of java string. I have checked this by adding the string "abcd" with the ressponse and printed the response string in logcat. But the result is the truncated respose without added string "abcd".
That is
try {
BasicResponseHandler responseHandler = new BasicResponseHandler();
String json = httpclient.execute(httpget, responseHandler);
json= json+"abcd";
Log.d("Json ResponseString", json);
} finally {
httpclient.close();
}
So I put an arrayString to collect the response. To make array, I splitted My json format response by using "}"
The code is given below(This is a work around only)
BasicResponseHandler responseHandler = new BasicResponseHandler();
String[] array=client.execute(request, responseHandler).split("}");
Then you can parse each objects in to a json object and json array with your custom classes.
If you get any other good method to store response, pls share because i am creating custom method for every different json responses );.
Thank you
Arshad
Hi Now I am using Gson library to handle the responses.
http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html
Thanks
Arshad
I cant' comment directly due to reputation, but in response to https://stackoverflow.com/a/23247290/4830567 I felt I should point out that the size limit of a Java String is about 2GB (Integer.MAX_VALUE) so this wasn't the cause of the truncation here.
According to https://groups.google.com/d/msg/android-developers/g4YkmrFST6A/z8K3vSdgwEkJ it is logcat that has a size limit, which is why appending "abcd" and printing in logcat didn't work. The String itself would have had the appended characters. The previously linked discussion also mentioned that size limits with the HTTP protocol itself can occasionally be a factor, but that most servers and clients handle this constraint internally so as to not expose it to the user.

How do I prevent my app from crashing unexpectedly, "force close", when using JSON data, and handle the exception instead?

In my application, I have a food activity in which the user enters his/her food, and the app requests the food, by the name entered by the user, from a MYSQL database. In the case that the entered food not exist, the string returned by the database should be null.
Currently, when this happens, an exception to occurs since the null value cannot be parsed to a JSON array. My question is: "Is there a way to prevent my app from force closing? Can I handle the exception and display a toast notifying the user that the requested food was not found?" I would like to prevent the app from crashing, and, rather, fail gracefully.
Please help me.
I've shown the relevant code in my application..
private class LoadData extends AsyncTask<Void, Void, String>
{
private JSONArray jArray;
private String result = null;
private InputStream is = null;
private String entered_food_name=choice.getText().toString().trim();
protected void onPreExecute()
{
}
#Override
protected String doInBackground(Void... params)
{
try {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.0.2.2/food.php");
nameValuePairs.add(new BasicNameValuePair("Name",entered_food_name));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
//convert response to string
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
result =sb.toString();
result = result.replace('\"', '\'').trim();
}
catch(Exception e){
Log.e("log_tag", " connection" + e.toString());
}
return result;
}
#Override
protected void onPostExecute(String result)
{
try{
String foodName="";
int Description=0;
jArray = new JSONArray(result); // here if the result is null an exeption will occur
JSONObject json_data = null;
for (int i = 0; i < jArray.length(); i++) {
json_data = jArray.getJSONObject(i);
foodName=json_data.getString("Name");
.
.
.
.
.
}
catch(JSONException e){
**// what i can do here to prevent my app from crash and
// make toast " the entered food isnot available " ????**
Log.e("log_tag", "parssing error " + e.toString());
}
}
}
This will fix your code:
jArray = (result == null) ? new JSONArray() : new JSONArray(result);
Now that you have an empty JSONArray, you will be able to test for null JSONObjects later in your program. Many of the JSON methods return a JSONObject if one is found, of null if none exists.
You might also want to initialize your JSONObject with the no-argument JSON constructor, rather than simply setting it to null. It will avoid problems when passing it to other JSON methods (such as using it in a constructor to a JSONArray():
JSONObject json_data = new JSONObject();
Finally, if you're still getting JSONExceptions, it's because you're not actually passing a valid JSON string to the constructor. You can print out the value of result to the log:
Log.d("JSON Data", result);
You may see some SQL error text or if you retrieve from a web server, then an HTTP error code (404 is common if you don't have your url correct).
If your result does look like JSON, then you can verify whether it's actually valid JSON or not using the JSONLint validator. It will help you catch any errors you may have, especially if you're formatting the JSON yourself.
Are you looking to capture the Exception and log it (remotely) to aid in crash reporting and debugging? I've used this package to remotely capture Exceptions and it works pretty good:
http://code.google.com/p/android-remote-stacktrace/

Categories

Resources