Reputation: 890
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
Upvotes: 2
Views: 6010
Reputation: 890
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.
Upvotes: 0
Reputation: 4132
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
Upvotes: 1
Reputation: 22527
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());
}
Upvotes: 0
Reputation: 41
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.
Upvotes: 0