我正在尝试解析像这样的JSON字符串(使用http://www.json-generator.com生成的URL)
{
"total": 86,
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"startDate": "14/03/2012",
"meetingId": "1330",
"creator": "Jhon",
"lastModified": "02/04/2012",
"meetingTitle": "task clarification",
"location": "Conf hall",
"startTime": "02:00 PM",
"createdDate": "14/03/2012",
"owner": "Peter",
"endTime": "02:30 PM"
},
{
"startDate": "20/03/2012",
"meetingId": "1396",
"creator": "Mr.Hobbs",
"lastModified": "07/09/2012",
"meetingTitle": "Design Work",
"location": "South conf Room",
"startTime": "03:30 PM",
"createdDate": "19/03/2012",
"owner": "Steve Jobs",
"endTime": "04:30 PM"
},
{
"startDate": "22/03/2012",
"meetingId": "1432",
"creator": "Robin",
"lastModified": "21/03/2012",
"meetingTitle": "Do something new",
"location": "NA",
"startTime": "10:00 AM",
"createdDate": "21/03/2012",
"owner": "Mr.Bean",
"endTime": "11:00 AM"
}
]
}
这是我正在使用的对象类:
public class Country {
String startDate;
String meetingId;
String creator;
String lastModified;
String meetingTitle;
String location;
String startTime;
String createdDate;
String owner;
String endTime;
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getMeetingId() {
return meetingId;
}
public void setMeetingId(String meetingId) {
this.meetingId = meetingId;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
public String getMeetingTitle() {
return meetingTitle;
}
public void setMeetingTitle(String meetingTitle) {
this.meetingTitle = meetingTitle;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
但它让我失望:
W/JSONStreamReader(1153): java.lang.IllegalStateException: Expected a name but was NUMBER at line 1 column 8
08-09 01:21:37.629: W/JSONStreamReader(1153): java.lang.IllegalStateException: Expected a name but was NUMBER at line 1 column 8
08-09 01:21:37.629: W/JSONStreamReader(1153): at com.google.gson.stream.JsonReader.nextName(JsonReader.java:785)
08-09 01:21:37.629: W/JSONStreamReader(1153): at com.example.gsontest.MainActivity$MyAsyncTask.doInBackground(MainActivity.java:162)
在Json“id”中:1,是数字!那是什么原因?我正在使用 http://www.json-generator.com
生成JSON我解析Json的Aysc代码:
private class MyAsyncTask extends AsyncTask<String, Void, Void> {
private static final int REGISTRATION_TIMEOUT = 3 * 1000;
private static final int WAIT_TIMEOUT = 30 * 1000;
private final HttpClient httpclient = new DefaultHttpClient();
final HttpParams params = httpclient.getParams();
private boolean error = false;
protected Void doInBackground(String... urls) {
String URL = null;
Log.d("ConnManagerParams", "ok?");
try {
// URL passed to the AsyncTask
URL = urls[0];
HttpConnectionParams.setConnectionTimeout(params,
REGISTRATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT);
ConnManagerParams.setTimeout(params, WAIT_TIMEOUT);
Log.d("ConnManagerParams", "ok?");
HttpPost httpPost = new HttpPost(URL);
Log.d("httpPost", "ok?");
// Response from the Http Request
HttpResponse response = httpclient.execute(httpPost);
Log.d("response", "ok?");
// Check the Http Request for success
StatusLine statusLine = response.getStatusLine();
Log.d("statusLine", response.getStatusLine().toString());
// Log.d("RESPONSE",
// EntityUtils.toString(response.getEntity()));
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
// Log.d("statusok", statusLine.getStatusCode());
Gson gson = new Gson();
// create a new JSON reader from the response input stream
Log.d("gson", "gson?");
JsonReader jsonReader = new JsonReader(
new InputStreamReader(response.getEntity()
.getContent(), "UTF-8"));
// begin parsing
Log.d("AFTjsonReader", "AFTjsonReader?");
jsonReader.beginObject();
Log.d("beginObject", "beginObject?");
// stay in loop as long as there are more data elements
while (jsonReader.hasNext()) {
// get the element name
Log.d("whilejsonReader", "whilejsonReader?");
// String name = jsonReader.nextName();
Log.d("nextName", jsonReader.nextName());
String name = jsonReader.nextName();
Log.d("nextNametest2", "nextName?");
if (name.equals("result")) {
Log.d("result", "result?");
jsonReader.beginArray();
while (jsonReader.hasNext()) {
// parse every element and convert that to a
// country object
Country country = gson.fromJson(jsonReader,
Country.class);
// add the country object to the list
countryList.add(country);
}
jsonReader.endArray();
}
// success = jsonReader.nextBoolean();
success = true;
}
// end reader and close the stream
jsonReader.endObject();
jsonReader.close();
} else {
// Closes the connection.
Log.d("Closes the connection.", "Closes the connection.?");
Log.w(LOG_TAG, statusLine.getReasonPhrase());
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (Exception e) {
Log.d("catch", "catch");
Log.w(LOG_TAG, e);
error = true;
cancel(true);
}
return null;
}
protected void onCancelled() {
Log.e(LOG_TAG, "Error occured during data download");
}
protected void onPostExecute(Void unused) {
if (error) {
Log.e(LOG_TAG, "Data download ended abnormally!");
} else {
displayCountries();
}
}
}
}
任何想法我该如何解决?
谢谢!
答案 0 :(得分:10)
你的代码中的问题是你循环名称(json键):
while (jsonReader.hasNext()) {
你得到了下一个名字:
String name = jsonReader.nextName();
但只有当此名称等于result
时才会使用该值。
将JsonReader
视为在json中向前移动光标的方法:通过令牌读取令牌。您给它的每个命令都可以读取光标指向的内容或移动光标,有时您可以移动光标并使用单个命令读取值(例如nextName()
)。
当名称不是result
时,jsonReader
会停留在您离开的位置:您刚刚使用nextName()
阅读的名称或密钥。
因此,下次调用nextName()
时,光标会从键移动到值(next
),并且它希望找到name
,而是找到前一个值名称,在您的情况下为NUMBER
,因为您的json中的第一个值是一个数字(名称:"total"
,值:56
)。
如果您因为不关心而没有阅读该值,则应致电
jsonReader.skipValue();
意味着您应该在
中更改代码if (name.equals("result")) {
// read it
} else {
jsonReader.skipValue();
}
那就是说:你应该使用注释,或者,如果由于某种原因你不能注册一个或多个TypeAdapter
来解析你的自定义对象。
这些适配器中的代码与您编写的代码非常相似,但它仅限于与您的对象匹配的json的单个部分。
例如,如果您创建的文章CountriesResult
包含您的total
和result
类型List<Country>
public class CountriesResult {
private int total;
@SerializedName("result")
private List<Country> countries;
}
您已经拥有了一个国家级别,其中包含您需要的字段。
然后你要求GSon解析它将自动解析它的CountriesResult
对象。
gson.fromJson(jsonString, CountriesResult.class);
如果您需要以自定义方式解析Country
,TypeAdatper
需要Country
,请参阅this示例。并register类型适配器或使用@JsonAdapter
annotation。
答案 1 :(得分:3)
如果您要使用JsonReader
并手动解析流,则不要通过Gson.fromJson()
使用自动反序列化。
您需要在循环中遍历该数组时从每个对象中提取字段,或者只是使用适当类的自动反序列化(老实说,这应该是您应该做的):
class Response {
private int total;
private String jsonrpc;
private int id;
private List<Country> result;
// getters and setters ...
}
然后简单地说:
InputStreamReader isr = new InputStreamReader(response.getEntity()
.getContent(), "UTF-8"));
Response r = gson.fromJson(isr, Response.class);
答案 2 :(得分:2)
我也面临同样的问题。我发现,问题是每个if条件我得到jsonReader.nextName()。这是不正确的方式。我认为你也是这样做的。
从你的代码中,这两行会产生问题。
// here the jsonReader moving one step.
Log.d("nextName", jsonReader.nextName());
//again your trying to getting the "jsonReader.nextName()" it is wrong in the above line already you got the name and reader move to next line. So Exception may be comes here.
String name = jsonReader.nextName();
我们应该只为while循环中的每次迭代使用“jsonReader.nextName()”一次
while (reader.hasNext())
{
String name=reader.nextName();
if(name.equals(Constants.AUTH)){
authDetails.setAuth(reader.nextString());
}else if(name.equals(Constants.STATUS)){
authDetails.setStatus(reader.nextInt());
}else if(name.equals(Constants.MESSAGE)){
authDetails.setMessage(reader.nextString());
}else {
reader.skipValue();
}
}