2

I'm fairly new to Android dev, and am trying to write a programme to parse some JSON from a website and output it in a ListView. However, when I run my programme, I get the error:

05-24 05:37:41.524: E/JSON Parser(783): Error parsing data org.json.JSONException: Value <?xml of type java.lang.String cannot be converted to JSONArray

Which is really odd, because there does not even seem to be a xml header in my JSON page. The JSON I'm trying to parse is:

[{"codeField":"COMPSCI 101","semesterField":"Summer School; Semester 1; Semester 2","titleField":"Principles of Programming"},{"codeField":"COMPSCI 105","semesterField":"Summer School; Semester 1; Semester 2","titleField":"Principles of Computer Science"},{"codeField":"COMPSCI 111\/111G","semesterField":"Summer School; Semester 1; Semester 2","titleField":"Mastering Cyberspace: An Introduction to Practical Computing"},{"codeField":"COMPSCI 210","semesterField":"Semester 1; Semester 2","titleField":"Computer Systems 1"},{"codeField":"COMPSCI 215","semesterField":"Semester 2","titleField":"Computer Systems 2"},{"codeField":"COMPSCI 220","semesterField":"Semester 2","titleField":"Algorithms and data structures"},{"codeField":"COMPSCI 225","semesterField":"Semester 1; Semester 2","titleField":"Discrete Structures in Mathematics and Computer Science"},{"codeField":"COMPSCI 230","semesterField":"Semester 1","titleField":"Software Design and Construction"},{"codeField":"COMPSCI 230","semesterField":"Semester 2","titleField":"Software Construction"}]

I know, the whitespacing is awful, but it's an external source that I can't change.

My code:

From the main activity:

public class AndroidJSONParsingActivity extends ListActivity {

private static String url = "http://redsox.tcs.auckland.ac.nz/734A/CSService.svc/courses";

private static final String TAG_CODE = "codeField";
private static final String TAG_SEMESTER = "semesterField";
private static final String TAG_TITLE = "titleField";

JSONArray courses = null;

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Hashmap for ListView
    ArrayList<HashMap<String, String>> courseList = new ArrayList<HashMap<String, String>>();

    JSONParser jParser = new JSONParser();
    courses = jParser.getJSONfromURL(url);

    try {
        for(int i = 0; i < courses.length(); i++){
            JSONObject c = courses.getJSONObject(i);

            // Storing each json item in variable
            String code = c.getString(TAG_CODE);
            String semester = c.getString(TAG_SEMESTER);
            String title = c.getString(TAG_TITLE);

            // creating new HashMap
            HashMap<String, String> map = new HashMap<String, String>();

            // adding each child node to HashMap key => value
            map.put(TAG_CODE, code);
            map.put(TAG_SEMESTER, semester);
            map.put(TAG_TITLE, title);

            // adding HashList to ArrayList
            courseList.add(map);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }


    //Updating parsed JSON data into ListView
    ListAdapter adapter = new SimpleAdapter(this, courseList,
            R.layout.list_item,
            new String[] { TAG_CODE, TAG_SEMESTER, TAG_TITLE }, new int[] {
                    R.id.code, R.id.semester, R.id.title });

    setListAdapter(adapter);

In the JSONParser class:

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";
    static JSONArray jArray = null;

    public JSONParser() {

    }

    public JSONArray getJSONfromURL(String url) {

        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();           

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // return JSON String
        try {
            jArray = new JSONArray(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }
        return jArray;

    }
}

Edit: Full logcat is:

05-24 06:48:55.347: D/dalvikvm(787): GC_CONCURRENT freed 68K, 8% free 2736K/2948K, paused 6ms+34ms, total 115ms
05-24 06:48:55.547: E/JSON Parser(787): Error parsing data org.json.JSONException: Value <?xml of type java.lang.String cannot be converted to JSONArray
05-24 06:48:55.547: D/AndroidRuntime(787): Shutting down VM
05-24 06:48:55.547: W/dalvikvm(787): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
05-24 06:48:55.577: E/AndroidRuntime(787): FATAL EXCEPTION: main
05-24 06:48:55.577: E/AndroidRuntime(787): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.androidhive.jsonparsing/com.androidhive.jsonparsing.AndroidJSONParsingActivity}: java.lang.NullPointerException
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.os.Handler.dispatchMessage(Handler.java:99)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.os.Looper.loop(Looper.java:137)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread.main(ActivityThread.java:5041)
05-24 06:48:55.577: E/AndroidRuntime(787):  at java.lang.reflect.Method.invokeNative(Native Method)
05-24 06:48:55.577: E/AndroidRuntime(787):  at java.lang.reflect.Method.invoke(Method.java:511)
05-24 06:48:55.577: E/AndroidRuntime(787):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
05-24 06:48:55.577: E/AndroidRuntime(787):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
05-24 06:48:55.577: E/AndroidRuntime(787):  at dalvik.system.NativeStart.main(Native Method)
05-24 06:48:55.577: E/AndroidRuntime(787): Caused by: java.lang.NullPointerException
05-24 06:48:55.577: E/AndroidRuntime(787):  at com.androidhive.jsonparsing.AndroidJSONParsingActivity.onCreate(AndroidJSONParsingActivity.java:44)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.Activity.performCreate(Activity.java:5104)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
05-24 06:48:55.577: E/AndroidRuntime(787):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
05-24 06:48:55.577: E/AndroidRuntime(787):  ... 11 more
17
  • which is the url ur trying to fetch? Commented May 24, 2013 at 5:56
  • That JSON response you have given above is not complete and exact response you are getting from web. I am 100% sure its covered by <?xml .....> tag. Post complete response here. Commented May 24, 2013 at 5:56
  • @PareshMayani.Although i deleted the answer,one should also question the reason of these questions which are actually meant for CHATS!! Commented May 24, 2013 at 6:03
  • @PareshMayani how do I get the complete and exact response from the web? Do you mean my logcat? I will edit my post to include it. Commented May 24, 2013 at 6:56
  • @Nezam I will edit my post to include the URL used in my code Commented May 24, 2013 at 6:56

4 Answers 4

1

Alhumdulillah.I finally got your problem..

You are making a POST request to this url but it is NOT ALLOWED.You should change the HTTP REQUEST to type GET

Just go to http://http-headers.online-domain-tools.com/

and check with POST AND GET

in POST your getting this response:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Service</title>
    <style>BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}</style>
  </head>
  <body>
    <div id="content">
      <p class="heading1">Service</p>
      <p xmlns="">Method not allowed. Please see the <a rel="help-page" href="http://redsox.tcs.auckland.ac.nz/734A/CSService.svc/help">service help page</a> for constructing valid requests to the service.</p>
    </div>
  </body>
</html>

Which is why you're getting that error!

So either you ALLOW POST from the server or you can do a bit of changing in the JSONParser class to change HttpPost to HttpGet.Look here

Sign up to request clarification or add additional context in comments.

Comments

0

You only create a json array in the json parser class. Then you try to fetch a json object. try

 try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    return jObj;

for the json parser class and this when you fetch it (in runtime) like this:

 class LoadAllProducts extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(ProductsView.this);
        pDialog.setMessage(resStrings.get(0));
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected String doInBackground(String... params) {
        List<NameValuePair> params1 = new ArrayList<NameValuePair>();
        JSONObject json = jParser.makeHttpRequest(UrlList.url_all_products, "GET", params1);
        Log.d(resStrings.get(1), json.toString());
        int success = 0;
        try {
            success = json.getInt(TagList.TAG_SUCCESS);
            if (success == 1) {
                final JSONArray products = json.getJSONArray(TagList.TAG_PRODUCTS);
                for (int i = 0; i < products.length(); i++) {
                    JSONObject c = products.getJSONObject(i);
                    String id = c.getString(TagList.TAG_PID);
                    String name = c.getString(TagList.TAG_PNAME);
                    String quantity = c.getString(TagList.TAG_PQUANTITY);
                    String price = c.getString(TagList.TAG_PPRICE);
                    String mod = c.getString(TagList.TAG_PMOD);

                    HashMap<String, String> map = new HashMap<String, String>();
                    map.put(TagList.TAG_PID, id);
                    map.put(TagList.TAG_PNAME, name);
                    map.put(TagList.TAG_PMOD, mod);
                    map.put(TagList.TAG_PQUANTITY, quantity);
                    map.put(TagList.TAG_PPRICE, price);
                    productsList.add(map);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String file_url) {
        pDialog.dismiss();
       runOnUiThread(new Runnable() {
          @Override
        public void run() {
                ListAdapter adapter = new SimpleAdapter(ProductsView.this, productsList, R.layout.list_item,  new String[] { TagList.TAG_PID, TagList.TAG_PNAME, TagList.TAG_PMOD, TagList.TAG_PQUANTITY, TagList.TAG_PPRICE }, new int[] { R.id.pid, R.id.pname, R.id.pmod, R.id.pquantity, R.id.pprice });
                setListAdapter(adapter);
                setProductList();
          }
       });
    }

Yeah I also have a class that uses a jsonString: I have this in a class

public static final String MAP_ONE = "{\"width\": \"7\", \"height\": \"7\", \"walls\" : [], \"charmain\" : [[0,0]], \"charenemy\" : [[0,6],[6,6]]}";

then a class factory

public class TileMapFactory {

public static ArrayList<Point> buildMap(final String tileMapJson) throws JSONException {

    ArrayList<Point> points = new ArrayList<Point>();

    final JSONObject jObject = new JSONObject(tileMapJson);
    final JSONArray jWalls = jObject.getJSONArray("walls");

    for (int i = 0; i < jWalls.length(); i++) {
        final JSONArray jWall = jWalls.getJSONArray(i);
        points.add(new Point((Integer) jWall.get(0), (Integer) jWall.get(1)));
    }

    return points;
}

}

and then you can access the string like this:

walls = TileMapFactory.buildMap(tileMap);
        for (int i = 0; i < walls.size(); i++) {
            mWorldMap[walls.get(i).x][walls.get(i).y].setType(Tile.TYPE_WALL);
        }

in this example the walls string is empty but when you replace the wall tag with the charenemy you'll have an array of 2 strings. then you can access the string like an arraylist by calling for example walls.get(i); In your case like codeField.

1 Comment

Frank, it seems like your JSON has 'products' in the first node? Mine starts right away with [{"codeField":"COMPSCI 101"..., instead of being {courses: [{"codeField":"COMPSCI 101"..., so I am not sure how to get a JSONArray from it in that case?
0

Adding new line can mess up your json string.
Try to change sb.append(line + "\n"); to sb.append(line); because "\n" will mess up your string.
Otherwise your code looks fine. I recommend you using AsyncTask task though in your case.

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line); // escape will mess up your json string
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

Comments

0

It works now. Thank you all. :) I simply used the methods in GSON instead - much easier. Appreciate all the help regardless.

And yes, the HttpPost should have been a HttpGet also.

1 Comment

You should've marked my answer as a solution to do justice to the post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.