Android - Parsing a JSON string - java

I'm trying to parse a simple JSON string
try {
String candyJson = "{\"candies\":[ {\"name\":\"Jelly Beans\", \"count\":10}, {\"name\":\"Butterscotch\", \"count\":6}]}";
JSONObject candiesJSONobject = new JSONObject(candyJson);
JSONArray candiesJSONarray = candiesJSONobject.getJSONArray("candies");
Log.v("JSONObject", candiesJSONarray.getJSONObject(0).getString("name"));
} catch (JSONException e){
Log.e("MYAPP", e.toString());
}
The code works fine in this state without catching any exception and prints JSONObject name in the Android Log.
However when I don't try to catch the exception as shown in the following example:
String candyJson = "{\"candies\":[ {\"name\":\"Jelly Beans\", \"count\":10}, {\"name\":\"Butterscotch\", \"count\":6}]}";
JSONObject candiesJSONobject = new JSONObject(candyJson);
JSONArray candiesJSONarray = candiesJSONobject.getJSONArray("candies");
Log.v("JSONObject", candiesJSONarray.getJSONObject(0).getString("name"));
Android Studio gives me unhandled exception error on all JSON methods. Is it necessary to catch JSONException when parsing a JSON or am I doing something wrong?

This is a Java feature actually :-) Please read more about it here.
The idea is that - if a method states that it will throw an (non-Runtime) Exception, all the calls of that method are required to catch this exception, just in case.
It does not mean that you are getting this exception in your code, you can only see that when you actually run it. But Java requires you to be prepared for a situation where such exception is thrown.

Well since you're working with the org.json... json objects, yes most of their methods do throw exceptions that you must catch and handle.
However if you don't want to handle each exception on it's own i suggest you create a json utils class that will handle those things for you.
For example for the JSONObject constructor you can make your own method like so
public static JSONObject createObjectFromString(String objectString) {
try {
return new JSONObject(objectString);
} catch (JSONException e) {
Log.e("MYAPP", e.toString());
}
}
and just reuse this method when you want to create a new json object.

Yes actually if any method is throwing Exception you need to catch that Exception.
This is called as Checked Exceptions or Compile Time Exceptions.
In your case methods like
JsonArray getJsonArray(String name)
or
JsonObject getJsonObject(String name)
check here http://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html#getJsonArray-java.lang.String-
are throwing ClassCastException So you either catch it or throw the exception.
Throwing Exception will lead to crash the app, So better Catch it.

If any method throws checked Exception, then caller can either handle this exception by catching it or can re throw it by declaring another throws clause in method declaration.
This is the reason Android Studio is showing unhandled exception error.

Related

Try Catch in Java | Json still crashes

try {
Log.e("getTrackerSettings | ", json);
trackerSettings = new Gson().fromJson(json, typeToken);
} catch ( IllegalStateException e) {
Log.e("getTrackerSettings inside catch | ", "");
e.printStackTrace();
trackerSettings = new TrackerSettings(1, "Hello", "73");
}
This code snippet will crash, and give the following:
E/getTrackerSettings inside try |: false
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sendiman.manager, PID: 13196
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BOOLEAN at line 1 column 6 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
As you can see, this does no make sense. The entire function is inside a larger try catch( Exception e) as well.
The fromJson method throws a com.google.json.JsonSyntaxException. It does not throw a java.lang.IllegalStateException. You're catching the wrong thing.
The text highlights why the JSON is bad, and that IllegalStateException came up as part of parsing it. It's a causal relationship. Think of exceptions not as 'this specific thing went wrong', but as an alternate return value. The fromJson call returns either a T object (the thing you're trying to parse), OR a JsonSyntaxException, and that JsonSyntaxException object (exceptions are just objects) contains the details. You can query it by assigning it to a variable, and its toString also just prints the details. 'some inner parsing code threw an IllegalStateException' is the detail here.
It looks like you're attempting to parse the string "true" or "false" as json. It's not valid JSON, in the sense that all JSON has to be a JSON object in its outermost level.
Replace catch (IllegalStateException) with catch (JsonSyntaxException) instead.
luk2302 Answered in comments.
Catch (JsonSyntaxException e)did catch the crash.
It still fail because you are trying to catch IllegalStateException and not JsonSyntaxException
From javadoc documentation the signature of fromJson is:
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException
try {
Log.e("getTrackerSettings | ", json);
trackerSettings = new Gson().fromJson(json, typeToken);
} catch (JsonSyntaxException e) {
Log.e("getTrackerSettings inside catch | ", "");
e.printStackTrace();
trackerSettings = new TrackerSettings(1, "Hello", "73");
}

Java Exception-throwing introspection

I have a question about Java method introspection, specifically concerning exceptions. Say I have the following code:
private String getCustomReportResponse(HttpsURLConnection customReportConnection) {
int responseCode = 0;
try {
responseCode = customReportConnection.getResponseCode();
return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
} catch (IOException e) {
translateIntoRelevantException(responseCode, e);
}
}
Let's say both statements in the try block are capable of throwing an IOException - in which case, the translateIntoRelevantException method is invoked, which looks like this:
private void translateIntoRelevantException(int responseCode, IOException e) {
if(is5xxResponseCode(responseCode)) {
throw new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
}
throw new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}
So, whatever happens, either a String is returned, or an exception is thrown. Except the getCustomReportResponse method does not compile without adding a return statement after the catch block, which is absolutely unreachable. In fact, if I put the contents of translateIntoRelevantException inside the catch block, it compiles, which seems daft to me.
I should add, the exceptions being thrown are runtime exceptions, but I've also tried making them checked exceptions, but the problem persisted.
Could someone please explain why?
This is a common problem that "rethrow" helper methods face.
The compiler does not know (and there is no way to indicate) that the method translateIntoRelevantException will never return.
As such, it thinks that there is a code-path that continues after try block. So you have to put in a "dead-code" return null (or throw new RuntimeException("should never come here").
You don't have to put it after the try block, you can put it inside the catch.
try {
responseCode = customReportConnection.getResponseCode();
return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
} catch (IOException e) {
translateIntoRelevantException(responseCode, e);
throw new RuntimeException("should never come here");
}
It's probably prettier to have the helper just return the exception instead of throwing it. Then you can do
throw translateIntoRelevantException(responseCode, e);
Compilation of getCustomReportResponse should not rely on the implementation of translateIntoRelevantException for multiple reasons:
implementation of translateIntoRelevantException might not be available (it could be in a separate class, in a separate library);
otherwise any change in translateIntoRelevantException could break all of the calling methods.
As an alternative you can return an exception and then throw it in a client code:
private IOException translateIntoRelevantException(int responseCode, IOException e) {
if(is5xxResponseCode(responseCode)) {
return new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
}
return new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}
then call it like this:
throw translateIntoRelevantException(responseCode, e);

How to throw Java SAXParseException for bad XML documents in Try/Catch

I am trying to parse elements out of a XML document. It works for most of them, but sometimes I may get a fatal error because I am given a badly formatted XML document. I want to ignore those cases when I get those XML documents by throwing an exception for it. The console gives me a SAXParseException, but when I call for it in the catch block, it is unable to. I wanted to do it in the JSP scriplet, but it will never be thrown since the scriplet is not actively searching for the SAXException.
I though the solution is to create a method to throw the exception, but again, it says that the SAXParseException will never be thrown in the try/catch statement. What is happening here?
public String parseElementsByTagNameInXML(Document doc, String tagName) throws SAXParseException
{
try{
return doc.getElementsByTagName(tagName).item(0).getTextContent();
}
catch(SAXParseException e){
System.out.println("Failure on Generating MessageID: " + e);
}
catch(NullPointerException e){
//will not spam the console with nullpointexception errors
}
catch(Exception e){
System.out.println("Failure on Generating MessageID: " + e);
}
return "";
}
Your method define that it will throws SAXParseException but your try catch is catching and consuming it without tossing it back up the line. Instead, I think it's printing it out.
Try removing that catch and the exception catch, then if it fail by SAXParseException, it'll throw it to whoever call that method.

unhandled exception org.json.jsonexception

I'm working on an android app, and the app must save a java object in json format into the SQLite database. I wrote the code for this operation, then they must extract the Json object and reconvert it into a Java Object.
When I try to call the method for deserializing the json object in to a string, I found this error in Android Studio:unhandled exception org.json.jsonexception
When I try to catch JSONException e the program runs but don't deserialize the json object.
This is the code for the method:
private void read() throws JSONException {
SQLiteDatabase db = mMioDbHelper.getWritableDatabase();
String[] columns = {"StringaAll"};
Cursor c = db.query("Alle", columns, null, null, null, null,null );
while(c.moveToNext()) {
String stringaRis = c.getString(0);
JSONObject jObj = new JSONObject(stringaRis);
String sPassoMed = jObj.getString("passoMed");
final TextView tView = (TextView) this.findViewById(R.id.mainProvaQuery);
tView.setText(sPassoMed);
// }
}
}
Can you help me please?
Yes, you need to catch the exception.
But when you catch it, you should not just throw it on the floor. Your application needs to do something about the exception. Or if you / it is not expecting an exception to occur at runtime, then at least you should report it. Here's a minimal example (for an Android app)
try {
...
JSONObject jObj = new JSONObject(stringaRis);
...
} catch (JSONException e) {
Log.e("MYAPP", "unexpected JSON exception", e);
// Do something to recover ... or kill the app.
}
Of course, this does not solve your problem. The next thing you need to do is to figure out why you are getting the exception. Start by reading the exception message that you have logged to logcat.
Re this exception message:
org.json.JSONException: Value A of type java.lang.String cannot be converted to JSONObject
I assume it is thrown by this line:
JSONObject jObj = new JSONObject(stringaRis);
I think that it is telling you is that stringaRis has the value "A" ... and that cannot be parsed as a JSON object. It isn't JSON at all.

How to properly handle important unchecked exceptions

I'm writing a library that wraps around a REST API. The wrapper I'm creating uses GSON to deserialize the json into my object. Basically, something like this...
public Post getPost(url) throws IOException {
String jsonString = httpClient.get(url);
Post p = gson.fromJson(jsonString, Post.class);
// return Post to client and let client do something with it.
}
If I understand correctly, IOException is a checked exception. I'm telling my client: Hey, buddy - you better watch out and recover from this exception. Now my client can wrap the call in a try/catch and determine what to do if there is some network failure.
The GSON fromJson() method throws a JsonSyntaxException. I believe this is unchecked in the Java world, as one of its super classes is RuntimeException, and also because I am not required to add a try/catch or another "throws" like IOException.
Assuming what I have said so far is correct - how exactly should the API and client handle this situation? If the json string is garbage, my client is going to fail miserably due to the JsonSyntaxException because it's unchecked.
// Client
PostService postService = new PostService();
try{
Post p = postService.getPost(urlString);
// do something with post
}catch (IOException){
// handle exception
}
// ok, what about a JsonSyntaxException????
What's the best way to handle these situations?
You are allowed to catch unchecked exceptions. Just add catch(JsonSyntaxException e) to your try-catch block. After you catch the JsonSyntaxException, you can either handle it or rethrow it as a checked exception.
Ex:
try{
//do whatever
}catch(JsonSyntaxException e){
e.printStackTrace();
// throw new Exception(e); //checked exception
}catch(IOException e){
e.printStackTrace();
}

Categories

Resources