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.

Answer from Sujay on Stack Overflow
🌐
GitHub
github.com › stleary › JSON-java › issues › 5
JSONObject#getString() returns a string literal - "null" instead of null when the value is null · Issue #5 · stleary/JSON-java
December 28, 2010 - This test case fails: public void testNull() throws Exception { JSONObject j; j = new JSONObject("{\"message\":\"null\"}"); assertFalse(j.isNull("message")); assertEquals("null", j.getString("messa...
Author   yusuke
🌐
GitHub
gist.github.com › iperdomo › 2867928
Handling null values (JSONObject) · GitHub
false false true true org.codehaus.jettison.json.JSONException: JSONObject["nonexistent"] not found.
Top answer
1 of 2
23

You can use get() instead of getString(). This way an Object is returned and JSONObject will guess the right type. Works even for null. Note that there is a difference between Java null and org.json.JSONObject$Null.

CASE 3 does not return "nothing", it throws an Exception. So you have to check for the key to exist (has(key)) and return null instead.

public static Object tryToGet(JSONObject jsonObj, String key) {
    if (jsonObj.has(key))
        return jsonObj.opt(key);
    return null;
}

EDIT

As you commented, you only want a String or null, which leads to optString(key, default) for fetching. See the modified code:

package test;

import org.json.JSONObject;

public class Test {

    public static void main(String[] args) {
        // Does not work
        // JSONObject jsonObj  = {"a":"1","b":null};

        JSONObject jsonObj  = new JSONObject("{\"a\":\"1\",\"b\":null,\"d\":1}");

        printValueAndType(getOrNull(jsonObj, "a")); 
        // >>> 1 -> class java.lang.String

        printValueAndType(getOrNull(jsonObj, "b")); 
        // >>> null -> class org.json.JSONObject$Null

        printValueAndType(getOrNull(jsonObj, "d")); 
        // >>> 1 -> class java.lang.Integer

        printValueAndType(getOrNull(jsonObj, "c")); 
        // >>> null -> null
        // throws org.json.JSONException: JSONObject["c"] not found. without a check
    }

    public static Object getOrNull(JSONObject jsonObj, String key) {
        return jsonObj.optString(key, null);
    }

    public static void printValueAndType(Object obj){
        System.out.println(obj + " -> " + ((obj != null) ? obj.getClass() : null)); 
    }
}
2 of 2
8

you can use optString("c") or optString("c", null)

as stated in the documentation

🌐
Oracle
docs.oracle.com › javaee › 7 › api › javax › json › JsonObject.html
JsonObject (Java(TM) EE 7 Specification APIs)
the string value to which the specified name is mapped, or null if this object contains no mapping for the name ... ClassCastException - if the value to which the specified name is mapped is not assignable to JsonString type ... Returns the string value of the associated JsonString mapping ...
Top answer
1 of 7
142

Use .has(String) and .isNull(String)

A conservative usage could be;

    if (record.has("my_object_name") && !record.isNull("my_object_name")) {
        // Do something with object.
      }
2 of 7
17

It might be little late(it is for sure) but posting it for future readers

You can use JSONObject optJSONObject (String name) which will not throw any exception and

Returns the value mapped by name if it exists and is a JSONObject, or null otherwise.

so you can do

JSONObject obj = null;
if( (obj = result.optJSONObject("ERROR"))!=null ){
      // it's an error , now you can fetch the error object values from obj
}

or if you just want to test nullity without fetching the value then

if( result.optJSONObject("ERROR")!=null ){
    // error object found 
}

There is whole family of opt functions which either return null or you can also use the overloaded version to make them return any pre-defined values. e.g

String optString (String name, String fallback)

Returns the value mapped by name if it exists, coercing it if necessary, or fallback if no such mapping exists.

where coercing mean, it will try to convert the value into String type


A modified version of the @TheMonkeyMan answer to eliminate redundant look-ups

public void processResult(JSONObject result) {
    JSONObject obj = null;
    if( (obj = result.optJSONObject("ERROR"))!=null ){
       //^^^^ either assign null or jsonobject to obj
      //  if not null then  found error object  , execute if body                              
        String error_detail = obj.optString("DESCRIPTION","Something went wrong");
        //either show error message from server or default string as "Something went wrong"
        finish(); // kill the current activity 
    }
    else if( (obj = result.optJSONObject("STATISTICS"))!=null ){
        String stats = obj.optString("Production Stats");
        //Do something
    }
    else
    {
        throw new Exception("Could not parse JSON Object!");
    }
}
🌐
Stleary
stleary.github.io › JSON-java › org › json › JSONObject.html
JSONObject
Get an array of field names from a JSONObject. ... An array of field names, or null if there are no names. ... Get an array of public field names from an Object. ... An array of field names, or null if there are no names. public String getString(String key) throws JSONException
Find elsewhere
🌐
Processing
processing.org › reference › JSONObject_isNull_.html
isNull() / Reference / Processing.org - JSONObject
January 1, 2021 - JSONObject json; void setup() { ... json.setString("species", null); if (json.isNull("species") == true) { println("The species is undefined"); } else { println("The ID is " + json.getString("species")); } } .isNull(key) key(String)A ...
🌐
Tabnine
tabnine.com › home page › code › java › org.json.jsonobject
org.json.JSONObject.isNull java code examples | Tabnine
public List<MyItem> read(InputStream inputStream) throws JSONException { List<MyItem> items = new ArrayList<MyItem>(); String json = new Scanner(inputStream).useDelimiter(REGEX_INPUT_BOUNDARY_BEGINNING).next(); JSONArray array = new JSONArray(json); for (int i = 0; i < array.length(); i++) { String title = null; String snippet = null; JSONObject object = array.getJSONObject(i); double lat = object.getDouble("lat"); double lng = object.getDouble("lng"); if (!object.isNull("title")) { title = object.getString("title"); } if (!object.isNull("snippet")) { snippet = object.getString("snippet"); } items.add(new MyItem(lat, lng, title, snippet)); } return items; }
🌐
Oracle
docs.oracle.com › middleware › maf240 › mobile › api-ref › oracle › adfmf › json › JSONObject.html
JSONObject (Oracle Fusion Middleware Java API Reference for Oracle Mobile Application Framework)
Increment a property of a JSONObject. If there is no such property, create one with a value of 1. If there is such a property, and if it is an Integer, Long, Double, or Float, then add one to it. ... JSONException - If there is already a property with this name that is not an Integer, Long, Double, or Float. ... Determine if the value associated with the key is null or if there is no value.
Top answer
1 of 10
124

You're not alone in running into this problem and scratching your head, thinking "Could they really have meant this?" According to an AOSP issue, the Google engineers did consider this a bug, but they had to be compatible with the org.json implementation, even bug-compatible.

If you think about it, it makes sense, because if the same code which uses the same libraries run in other Java environments behaves differently in Android, there would be major compatibility problems when using 3rd party libraries. Even if the intentions were good and it truly fixed bugs, it would open up a whole new can of worms.

According to the AOSP issue:

The behavior is intentional; we went out of our way to be bug-compatible with org.json. Now that that's fixed, it's unclear whether we should fix our code as well. Applications may have come to rely on this buggy behavior.

If this is causing you grief, I recommend you workaround by using a different mechanism to test for null, such as json.isNull().

Here's a simple method to help you out:

/** Return the value mapped by the given key, or {@code null} if not present or null. */
public static String optString(JSONObject json, String key)
{
    // http://code.google.com/p/android/issues/detail?id=13830
    if (json.isNull(key))
        return null;
    else
        return json.optString(key, null);
}
2 of 10
25

You basically have 2 choices:

1) Send a JSON payload with null values

{
"street2": "s2",
"province": "p1",
"street1": null,
"postalCode": null,
"country": null,
"city": null
}

You will have to check for null values and parse them accordingly:

private String optString_1(final JSONObject json, final String key) {
    return json.isNull(key) ? null : json.optString(key);
}

2) Do not send the keys with null values and use optString(key, null) directly (should save you bandwidth).

{
"street2": "s2",
"province": "p1"
}
🌐
Microsoft Learn
learn.microsoft.com › en-us › dotnet › api › org.json.jsonobject.null
JSONObject.Null Property (Org.Json) | Microsoft Learn
A sentinel value used to explicitly define a name with no value. Unlike null, names with this value: <ul> <li>show up in the #names array <li>show up in the #keys iterator <li>return true for #has(String)<li>do not throw on #get(String)<li>are ...
🌐
Kotlin Discussions
discuss.kotlinlang.org › android
Kotlin JSONObject$Null Bug - Android - Kotlin Discussions
April 5, 2018 - Hey, Im new here, so sorry if i posted this in the wrong section! I just found this bug for Kotlin while using the org.json library. When JSON returns null, it gives a JSONObject$Null While checking for null, == fails, and .equals warns to use == My code: fun testNullJSON(jsonObject: JSONObject, valueKey: String){ val jsonArray = jsonObject.getJSONArray(valueKey) for(i in 0 until jsonArray.length()) { val jsonArrayValue = jsonArray[i] ?: continue // NOTE: First null check here w...
🌐
ArduinoJson
arduinojson.org › version 6 › api › jsonobject › isnull()
JsonObject::isNull() | ArduinoJson 6
StaticJsonDocument<200> doc; deserializeJson(doc, "[\"hello\",\"world\"]"); JsonObject object = doc.as<JsonObject>(); Serial.println(object.isNull()); // true
🌐
Stack Overflow
stackoverflow.com › questions › 26669742 › java-check-null-faile-for-result-of-jsonobject
json - Java check null faile for result of JSONObject - Stack Overflow
If I understand the problem correctly, you only want to the value of a property in the JSON if it's not null, "null" or empty. Try the following code: if (data_array.has("ok") && data_array.getString("ok") != null && !data_array.getString("ok").trim().equals("") && !data_array.getString("ok").equals("null")) { o = data_array.getString ( "ok" ); }