I made a small MVC4 app wich returns data from an SQL server as an API, the local url is http://10.0.0.116:35577/api/articoli
(I have already enabled network access to the local IIS instance, this actually stopped me for a whole day until I figured it out), the format it returns is the following:
我做了一个小型的MVC4应用程序,它从SQL服务器返回数据作为API,本地URL是http://10.0.0.116:35577/api/articoli(我已经启用了对本地IIS实例的网络访问,这实际上停止了我整整一天直到我发现它,它返回的格式如下:
[{"id":0,"desc":"Pizza"},{"id":1,"desc":"Pasta"},{"id":2,"desc":"Science"},{"id":3,"desc":"spaghetti"},{"id":4,"desc":"sfas"},{"id":5,"desc":"test"}]
calling http://10.0.0.116:35577/api/articoli/1
returns a single element:
调用http://10.0.0.116:35577/api/articoli/1返回一个元素:
{"id":1,"desc":"Pasta"}
I've been having trouble parsing this from my android app, from what I gather that array is supposed to have a header name or something, which is totally absent here and I can't really figure how to add it in here, or if I really need to have one at all.
我一直无法从我的Android应用程序解析这个,从我收集的数据应该有一个标题名称或其他东西,这里完全没有,我不知道如何在这里添加它,或者如果我真的需要一个。
From what I can gather the parser class I got from a tutorial is not suited to this kind of data and I can't really figure out how to make it work with such a result.
从我可以收集到的,我从教程中获得的解析器类不适合这种数据,我无法弄清楚如何使它与这样的结果一起工作。
The parser is the following:
解析器如下:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
URL aaa = new URL(url);
URLConnection uConnection = aaa.openConnection();
uConnection.connect();
//is = httpEntity.getContent();
is = aaa.openStream();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, /*"UTF-8"*/ "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 parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
I had to edit the url retrieval part of the parser because it tried to get the data by using POST, which the server application interpreted as an attempt at inserting data and called the wrong method,
我必须编辑解析器的url检索部分,因为它试图通过使用POST获取数据,服务器应用程序将其解释为尝试插入数据并调用错误的方法,
And this is piece of code in which the parser is called, it's supposed to retrieve each element and then place each one as a row in a listview, which then clicked should call an activity that will read a single element:
这是调用解析器的一段代码,它应该检索每个元素,然后将每个元素作为一行放在listview中,然后单击它应该调用一个将读取单个元素的活动:
private void fillDataJSON() {
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(URL);
JSONArray articoli;
try {
articoli = json.getJSONArray("Articoli");
if (articoli == null) {
throw new NullPointerException();
}
for(int i = 0; i< articoli.length(); i++) {
JSONObject c = articoli.getJSONObject(i);
String id = c.getString(KEY_ID);
String desc = c.getString(KEY_DESC);
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_ID, id);
map.put(KEY_DESC, desc);
menuItems.add(map);
adapter = new SimpleAdapter(ApiTest.this, menuItems,
R.layout.activity_api_test_row,
new String[] { KEY_DESC },
new int[] { R.id.TextView01 });
}
} catch (JSONException e) {
e.printStackTrace();
}
}
The error I get is the following:
我得到的错误如下:
03-13 10:05:33.291: E/JSON Parser(11811): Error parsing data org.json.JSONException: Value [{"id":0,"desc":"Pizza"},{"id":1,"desc":"Pasta"},{"id":2,"desc":"Science"},{"id":3,"desc":"spaghetti"},{"id":4,"desc":"sfas"},{"id":5,"desc":"test"}] of type org.json.JSONArray cannot be converted to JSONObject
Can this be fixed on the android side or do I have to change how my server works?
这可以在android端修复,还是我必须改变服务器的工作方式?
The server just returns the data through the controller and everything else is left to the framework, example:
服务器只是通过控制器返回数据,其他所有内容都留给框架,例如:
public IEnumerable<Articoli> GetAllArticoli()
{
return repository.GetAll();
}
doesn't do anything other than that
除此之外什么都不做
2 个解决方案
#1
3
The root element of a JSON document can be either a JSONObject or a JSONArray (or one of the primitives). You're always parsing it as an object:
JSON文档的根元素可以是JSONObject或JSONArray(或其中一个基元)。你总是把它解析为一个对象:
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
You should parse it as a new JSONArray(json)
when the document's root element is an array. You can do this safely by using JSONTokener
:
当文档的根元素是数组时,您应该将其解析为新的JSONArray(json)。您可以使用JSONTokener安全地执行此操作:
// try parse the string to a JSON object
try {
JSONTokener jt = new JSONTokener(json);
Object rootElement = jt.nextValue();
if (rootElement instanceof JSONObject) {
// You got an object from the response
} else if (rootElement instanceof JSONArray) {
// You got a JSON array
}
// else... -> it can also be String, Boolean, Integer, Long or Double
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
If you know what you're requesting then it's easier to just use the correct response type.
如果您知道您要求的是什么,那么使用正确的响应类型会更容易。
#2
1
You can simply change your code inside fillDataJSON()
.Just change the type from JSONObject
to JSONArray
您只需更改fillDataJSON()中的代码即可。只需将类型从JSONObject更改为JSONArray即可
JSONArray json = jParser.getJSONFromUrl(URL);
JSONArray articoli;
try {
articoli = json;
and in your JSONParser
change to:
并在您的JSONParser中更改为:
// try parse the string to a JSON object
try {
jObj = new JSONArray(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
and change the type of jObj to JSONArray
并将jObj的类型更改为JSONArray
static JSONArray jObj = null;
and the return type of the class from JSONObject
to JSONArray
以及从JSONObject到JSONArray的类的返回类型
public JSONObject getJSONFromUrl(String url) {
#1
3
The root element of a JSON document can be either a JSONObject or a JSONArray (or one of the primitives). You're always parsing it as an object:
JSON文档的根元素可以是JSONObject或JSONArray(或其中一个基元)。你总是把它解析为一个对象:
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
You should parse it as a new JSONArray(json)
when the document's root element is an array. You can do this safely by using JSONTokener
:
当文档的根元素是数组时,您应该将其解析为新的JSONArray(json)。您可以使用JSONTokener安全地执行此操作:
// try parse the string to a JSON object
try {
JSONTokener jt = new JSONTokener(json);
Object rootElement = jt.nextValue();
if (rootElement instanceof JSONObject) {
// You got an object from the response
} else if (rootElement instanceof JSONArray) {
// You got a JSON array
}
// else... -> it can also be String, Boolean, Integer, Long or Double
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
If you know what you're requesting then it's easier to just use the correct response type.
如果您知道您要求的是什么,那么使用正确的响应类型会更容易。
#2
1
You can simply change your code inside fillDataJSON()
.Just change the type from JSONObject
to JSONArray
您只需更改fillDataJSON()中的代码即可。只需将类型从JSONObject更改为JSONArray即可
JSONArray json = jParser.getJSONFromUrl(URL);
JSONArray articoli;
try {
articoli = json;
and in your JSONParser
change to:
并在您的JSONParser中更改为:
// try parse the string to a JSON object
try {
jObj = new JSONArray(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
and change the type of jObj to JSONArray
并将jObj的类型更改为JSONArray
static JSONArray jObj = null;
and the return type of the class from JSONObject
to JSONArray
以及从JSONObject到JSONArray的类的返回类型
public JSONObject getJSONFromUrl(String url) {