简体   繁体   中英

JSON parsing error (Android)

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

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

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.

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());
    }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM