Namratha
Namratha

Reputation: 16790

java.lang.ClassCastException: java.lang.String JSON Tokener android

The following is my code. It works fine on the emulator. But when I run it on my android device, it crashes with java.lang.ClassCastException: java.lang.String at the line marked below. I can't find the place where the casting has gone wrong. Any help would be greatly appreciated! :)

 public static MatrixCursor getRespAsCursor(String query) {
    String url = (String)(API_URL + "?api_key=" + API_KEY + "&" + query);
    System.out.println(url);
    String resp = (String)getAPIResp(url);
    JSONObject reply;
    MatrixCursor emptyCursor = new MatrixCursor(new String[0]);

    try {
        reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE
        String statusCode = (String)reply.getString("statusCode");
        if(!statusCode.equals("200")) {
            return emptyCursor;
        }
        int count = Integer.parseInt(reply.getString("count"));
        if(count < 1) {
            return emptyCursor;
        }

        JSONArray data = reply.getJSONArray("data");

        //Get keys in String[] format
        Iterator<String> keys = data.optJSONObject(0).keys();
        List<String> copy = new ArrayList<String>();

        //Add "_id" as adapters need it for traversal
        copy.add("_id");

        //copy rest of the keys
        while (keys.hasNext())
            copy.add(keys.next());
        String[] sKeys = new String[copy.size()];
        copy.toArray(sKeys);

        int len = data.length();

        //Create Cursor with JSON keys as columns
        MatrixCursor resultCursor = new MatrixCursor(sKeys, len);

        //Add rows to Cursor
        for(int i = 0; i < len; i++) {
            JSONObject d = data.optJSONObject(i);
            List<Object> values = new ArrayList<Object>();
            for(String key: copy) {
                if(key.equals("_id")) {
                    values.add(Integer.toString(i));
                }
                else {
                    values.add(d.opt(key));
                }
            }
            resultCursor.addRow(values);
        }

        return resultCursor;
    }
    catch(JSONException e) {
        return emptyCursor;
    }

}

Upvotes: 0

Views: 1540

Answers (3)

wns349
wns349

Reputation: 1306

You might wanna have a look at JSONTokener javadoc

The doc says nextValue()

Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.

You are probably getting the ClassCastException as your line of code

 reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE

does not return JSONObject.

You might want to check instance type of the returned object before typecasting it. For example,

Object obj = new JSONTokener(resp).nextValue();
if(obj instanceof JSONObject){
  reply = (JSONObject)obj;
} else {
  //Handle otherwise,
}

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1503629

You've already shown the place the casting goes wrong - it's here:

reply = (JSONObject) new JSONTokener(resp).nextValue();

nextValue() is returning a String, and you're casting it to JSONObject.

I suspect the JSON isn't as you expect it to be - it's not a statusCode = "value" pair; it's just the value.

You should check the JSON that you're returning, and either change to cast to a string, or if you want to be able to handle both forms of JSON, check the result with instanceof before casting:

Object reply = new JSONTokener(resp).nextValue();
if (reply instanceof String) {
   ...
} else if (reply instanceof JSONObject) {
   ...
}

Upvotes: 5

Blackbelt
Blackbelt

Reputation: 157487

 reply = (JSONObject) new JSONTokener(resp).nextValue();//CRASHES HERE

If you are getting a ClassCastException is because the Object returned by nextValue() is not a JSONObject (probably a String instance)

Upvotes: 1

Related Questions