25

I have a response coming back from a server and I am expecting a String value, so I wrote this for parsing it

public String getMessageFromServer(JSONObject response) {
    String msg = response.getString("message");
    return msg;
}

then, when I use this in my code and get a null value from the server, the function doesn't return null, it returns "null" instead.

I have seen this bug report, but I don't see a solution.

EDIT:

I have a small hack to solve this but it's ugly and I'm looking for a better solution:

public String getMessageFromServer(JSONObject response) {
    Object msg = response.get("message");
    if(msg == null) {
         return null;
    }
    return (String) msg;
}    

EDIT #2:

after years, going back to this question, I see that I was not entirely wrong here and that JSONObject has a built in method for this.

The way to get an optional value from a JSONObject is with using this method JSONObject.optString("message", DEF_VALUE);

thepoosh
  • 12,497
  • 15
  • 73
  • 132
  • 1
    it is ok, but it's an ugly hack and I dislike it – thepoosh Oct 29 '12 at 08:36
  • 1
    Why is that ugly or a hack? You are just doing it well – Javier Diaz Oct 29 '12 at 08:37
  • 1
    it's ugly because, I expect a String value (that can be `null`) but have to deal with type casting. – thepoosh Oct 29 '12 at 08:40
  • Would checking for "null", in the first example, be less ugly? – ignis Oct 29 '12 at 08:45
  • it'll be time consuming, testing for the `null` value takes almost no time, testing for value of `String` takes a long time. – thepoosh Oct 29 '12 at 08:49
  • 1
    @thepoosh - you are optimizing prematurely. It is highly unlikely that the difference between `==` and `String.equals` will be significant. – Stephen C Oct 29 '12 at 09:15
  • @thepoosh Please note that `JSONObject.optString()` does coerce `JSONObject.NULL` to string with value `"null"` too. In other words `"null".equals(new JSONObject().put("test", JSONObject.NULL).optString("test", null))` gives `true`. – vlp Nov 24 '20 at 00:13
  • The way to get an optional value from a JSONObject is with using this method JSONObject.optString("message", DEF_VALUE); This worked for me! Thank you – wishman Oct 04 '22 at 00:21

3 Answers3

26

The hack looks okay for your situation.

The other option would be to use the method boolean isNull(String key) and then based on the returned boolean value proceed with your option. Something like:

public String getMessageFromServer(JSONObject response) {
    return ((response.has("message") && !response.isNull("message"))) ? response.getString("message") : null;
} 

But then, I don't think there's much of a difference between the your current implementation and this.

Sujay
  • 6,753
  • 2
  • 30
  • 49
  • 2
    +1 for pointing out the correct method to check for a null value. But I don't agree when you say there is not much difference. The isNUll-call is cleaner and should be preferred towards relying on Object and casting. – EinLama Jun 21 '13 at 09:40
  • 1
    can't you remove the `response.has("message)"` check? Whenever that key doesn't exist, `isNull` will return true, so `getString` won't be called and no exception will be thrown. – Mateus Gondim May 18 '17 at 22:02
3

This is easy to solve when using Kotlin class extensions:

fun JSONObject.optNullableString(name: String, fallback: String? = null) : String? {
    return if (this.has(name) && !this.isNull(name)) {
        this.getString(name)
    } else {
        fallback
    }
}

Then e.g. name will be null in:

val name : String? = JSONObject("""{"id": "foo", "name":null}""").optNullableString("name")
jhavatar
  • 3,236
  • 1
  • 18
  • 11
0

More simple way in Kotlin

fun JSONObject.getNullableString(name: String) : String? {
    if (has(name) && !isNull(name)) {
        return getString(name)
    }
    return null
}
Vlad
  • 7,997
  • 3
  • 56
  • 43