2

My program is handling some JSON data. I want the program to be really stable over time and the JSON data can change as their source is being updated and improved. This is current function to return some image file name from the data:

@Override
public String createImgName() {
  try {
    // data["image"]["full"]
    return getJSONData().getJSONObject("image").getString("full");
  }
  catch(JSONException e) {
    try {
      // data["id"] + ".png"
      return  getJSONData().getJSONObject("id")+".png"; 
    }
    catch(JSONException e2) {
      return null;
    }
  }
}

There's a few more things I could try to get the image name. But the program would grow quite ugly.

Is there a syntax for trying multiple things until one succeeds? In my case, the return statement breaks the program on success, but that may not allways be the case.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 1
    In short, the answer is no - you can't try multiple things until one succeeds. – Nayuki May 01 '15 at 18:03
  • 1
    Note that you're using `try-catch` as 'flow control'. This is almost certainly not what you want, and best practices advise avoiding it. – Nathaniel Ford May 01 '15 at 18:07
  • You can do the second try after/outside the catch as well. If no exception happens the code would have returned. There are some differences, but it is not clear which one is better. Of course avoiding the exception in the first place is better. – eckes May 01 '15 at 18:32
  • @NathanielFord I understand what you mean, but JSON library throws exception on almost every operation which quite enforces me to write the code like this. – Tomáš Zato May 01 '15 at 19:19

3 Answers3

8

Instead of having multiple try statements, you can check for the possible keys using .has() or .isNull() method.

More information: http://www.json.org/javadoc/org/json/JSONObject.html#has(java.lang.String) http://www.json.org/javadoc/org/json/JSONObject.html#isNull(java.lang.String)

For example:

@Override
public String createImgName() {
  try {
    JSONObject data = getJSONData();
    // data["image"]["full"]
    if (data.has("image")) {
      return data.getJSONObject("image").getString("full");
    } else if (data.has("id")) {
      return data.getJSONObject("id")+".png";
    }
  }
  catch(JSONException e) {
    return null;
  }
}
1

I would suggest using if/else blocks instead (best-practice) of try/catch. But for the try/catch you do need I suggest using a railway oriented programming to keep them down to a minimum.

http://fsharpforfunandprofit.com/posts/recipe-part2/

Richard
  • 122
  • 12
1

To answer the question posted, which is if you can use try on multiple things without nesting the try-catch statements, no.

However, what you can do though is, aside from an if-else as posted in one of the answers, you can catch multiple things.

So perhaps you might want a combination of both controls:

Instead of having getJSONData throw exceptions, you could just have it return null, in which you will have a nice flow control of if-else statements, all inside a try-catch, and if something really bad/exceptional happens, throw the a specific exception, and the corresponding catch statement will handle it.

The reason why try-catches are not a good flow control: Exceptions are costly when thrown, because of the stack trace it has to hold even if not used, this is fine in quick and dirty programming, but not in situations where performance is key.That is why exceptions should only be thrown if they are truly exceptional. See this opinion based Q&A on true-false vs exceptions, where my elaboration on that issue is located as well.

Something like this would be good:

public string imgName()
{ 
  try
  {
    JSONdata a = getJSONmethodA();  
    if(a == null) 
        a = getJSONmethodB(); 
    if(a == null) 
        a = getJSONmehtodC();
    return a;
  }
  catch(Exception unresolvableExceptionA)
  { 
       //error handling 
  }
  catch(Exception verybadExceptionB)
  {
       //special error handling for exception B
  }

}

Here's a related SO question on this multiple catch structure.

You can also add a finally in a try-catch for code that will always execute regardless of whether your try was successful or not. This is useful in closing connections, or return true/false depending on your needs as a status code for other functions that use that method.

Community
  • 1
  • 1
matrixanomaly
  • 6,627
  • 2
  • 35
  • 58