Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

instanceof JSONObject doesn't detect JSONObject

Tags:

json

android

I found strange behaviour of variable instanceof JSONObject. I have following code:

Object value;
try {
    value = customer.get(key);
    Log.v("type", String.valueOf(value.getClass())); // Returns JSONObject
    if (value instanceof JSONObject) {
        // Handle JSONObject
    } else {
        String text = (String)value;  // HERE COMES THE ERROR
        // Handle String
    }

When log returns JSONObject it ends up with exception:

01-15 12:24:46.206 4111-4111/cz.jacon.goldympos V/CUSTOMER type: class org.json.JSONObject$1
01-15 12:24:46.207 4111-4111/cz.jacon.goldympos D/AndroidRuntime: Shutting down VM
01-15 12:24:46.279 4111-4111/cz.jacon.goldympos E/AndroidRuntime: FATAL EXCEPTION: main
                   Process: cz.jacon.goldympos, PID: 4111
                   java.lang.RuntimeException: Unable to start activity ComponentInfo{cz.jacon.goldympos/cz.jacon.goldympos.activities.CustomerDetailActivity}: java.lang.ClassCastException: org.json.JSONObject$1 cannot be cast to java.lang.String
                            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
                            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                            at android.app.ActivityThread.access$800(ActivityThread.java:151)
                            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                            at android.os.Handler.dispatchMessage(Handler.java:102)
                            at android.os.Looper.loop(Looper.java:135)
                            at android.app.ActivityThread.main(ActivityThread.java:5254)
                            at java.lang.reflect.Method.invoke(Native Method)
                            at java.lang.reflect.Method.invoke(Method.java:372)
                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                            Caused by: java.lang.ClassCastException: org.json.JSONObject$1 cannot be cast to java.lang.String
                            at cz.jacon.goldympos.activities.CustomerDetailActivity.getText(CustomerDetailActivity.java:260)
                            at cz.jacon.goldympos.activities.CustomerDetailActivity.createLayout(CustomerDetailActivity.java:222)
                            at cz.jacon.goldympos.activities.CustomerDetailActivity.onCreate(CustomerDetailActivity.java:92)
                            at android.app.Activity.performCreate(Activity.java:5990)
                            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
                        ...........

Am I missing something? It looks so simple...

EDIT: json

Example of json I using. First is JSONObject, second is Integer (can be casted to String)

{
"viewers_edit_time":
    {
     "date":"2016-01-14 22:53:56.000000",
     "timezone_type":3,
     "timezone":"Asia/Kolkata"
    },
"viewers_edit_users_id":1
}

That's full json, exactly the same I'm using. And again:

Log.v("type", String.valueOf(value.getClass())); // Returns JSONObject not JSONObject$1

SOLVED

Problem solved. From the full JSON I've posted in question:

"viewers_postcode": null

I didn't noticed that null isn't in quotation marks... Before I was thinking that i was "null" which is String. I was mistaken by error message I got, which says JSONObject$1 cannot be casted to String. But JSONObject$1 is NULL (credits to @Natix)

Maybe it helps to other people with the same error message.

like image 831
kristyna Avatar asked Jan 29 '26 01:01

kristyna


1 Answers

You need to pay careful attention to the log message. The point is that org.json.JSONObject$1 is not the same as class org.json.JSONObject.

The $1suffix means it's an anonymous inner class of the JSONObject class. If you look in the source, you'll find this bit of code:

public static final Object NULL = new Object() {
    @Override public boolean equals(Object o) {
        return o == this || o == null; // API specifies this broken equals implementation
    }
    @Override public String toString() {
        return "null";
    }
};

This means that you should first check if your value is equal to this NULL constant:

Object value = customer.get(key);
if (value == JSONObject.NULL {
    // Handle NULL
} else if (value instanceof JSONObject) {
    // Handle JSONObject
} else {
    // Handle String
}
like image 139
Natix Avatar answered Jan 30 '26 18:01

Natix