Ошибка ссылки на нулевой объект Android JSON
Я использую API StackExchange в своем приложении, которое возвращает ответ, подобный этому:
{
"items":[
{
"tags":[
"android",
"gridview",
"android-fragments",
"android-activity"
],
"owner":{
"reputation":30,
"user_id":3303863,
"user_type":"registered",
"profile_image":"https://stackru.com/images/9fa2cb36643a848bc6e0aed01ad215141e28dc86.jpg?s=128&g=1",
"display_name":"chris.b",
"link":"http://stackru.com/users/3303863/chris-b"
},
"is_answered":false,
"view_count":7,
"answer_count":0,
"score":0,
"last_activity_date":1429979620,
"creation_date":1429979620,
"question_id":29867827,
"link":"http://stackru.com/questions/29867827/android-app-close-without-error-on-click-of-the-first-gridview-item",
"title":"Android App Close without Error, on click of the first gridview Item"
},
{
"tags":[
"android",
"genymotion"
],
"owner":{
"reputation":61,
"user_id":213199,
"user_type":"registered",
"accept_rate":54,
"profile_image":"https://www.gravatar.com/avatar/2f0b0c0e0e449255b5e2892b10b97ba4?s=128&d=identicon&r=PG",
"display_name":"Stella",
"link":"http://stackru.com/users/213199/stella"
},
"is_answered":false,
"view_count":7,
"answer_count":0,
"score":0,
"last_activity_date":1429979268,
"creation_date":1429979268,
"question_id":29867773,
"link":"http://stackru.com/questions/29867773/unable-to-run-android-app-in-genymotion-emulator",
"title":"Unable to run Android app in Genymotion emulator"
},
И я использую следующий код, чтобы получить строку из URL:
public String readJSON() {
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = null;
try {
response = client.execute(httpGet);
} catch (IOException e) {
e.printStackTrace();
}
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = null;
try {
content = entity.getContent();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
try {
while ((line = reader.readLine()) != null) {
builder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
//Log.e(re.class.toString(), "Failed to download file");
}
return builder.toString();
}
и я использую задачу Async для отображения вопросов в текстовом виде, как это:
public class JSONTask extends AsyncTask<String,String,JSONObject>
{
private ProgressDialog pDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Getting Data ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected JSONObject doInBackground(String... params) {
try {
ob1 = new JSONObject(readJSON());
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return ob1;
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
try {
mJSONArr = jsonObject.getJSONArray("items");
for(int i=0;i<20;i++)
{
ob2 = mJSONArr.getJSONObject(i);
holder+=ob2.getString("title");
}
tv.setText(holder);
pDialog.dismiss();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Но я получаю сообщение об ошибке
"Попытка вызвать виртуальный метод" org.json.JSONObject org.json.JSONArray.getJSONObject(int)'для пустой ссылки на объект "
на этих линиях:
mJSONArr = ob1.getJSONArray("items");
а также
public class JSONTask extends AsyncTask<String,String,JSONObject>
Как это исправить? Кроме того, как мне получить доступ к "отображаемому имени" из объекта "владелец" в этом ответе JSON?
Спасибо
2 ответа
Для доступа к заголовкам вы должны получить доступ к массиву JSON items
сначала, а затем получить доступ к его пунктам JsonObject MyJson =YourJsonArray.getJsonObject(i)
после этого используйте тег, который вы хотите пример String title=Myjson.getString("title")
вот что вы меняете в своем коде
@Override
protected void onPostExecute(JSONObject jsonObject) {
pDialog.dismiss();//hiding the progress dialog
try {
if(ob1!=null && !ob1.isNull("items")){ //avoiding exceptions
mJSONArr = ob1.getJSONArray("items");
for(int i=0;i<mJsonArr.length();i++)
{
ob2 = mJSONArr.getJSONObject(i);
holder+=ob2.getString("title");
}
tv.setText(holder);
pDialog.dismiss();
} catch (JSONException e) {
e.printStackTrace();
}
}}
Изменить: вы получаете эту ошибку, потому что вы используете "i<20" вместо "i
Eit2: для диалога прогресса добавьте это в пост Выполнить
pDialog.dismiss();
Edit3: использовать этот класс JSONParser.java
package YourPackage;
import android.app.Application;
import android.os.Debug;
import android.util.Log;
import android.widget.Toast;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
// function get json from url
// by making HTTP POST or GET mehtod
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
// request method is POST
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
// request method is GET
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e){};
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
System.out.println(json);
} 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;
}
}
добавить это как глобальную переменную
JSONParser jsonParser = new JSONParser();
и в вашем asyncTask используйте это
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("key",key));//if you have params
ob1= jsonParser.makeHttpRequest(Your_url,
"POST" or "GET", params); //choose post method or get method
это
ob1 = new JSONObject(readJSON());
Здесь нет ob1
в onPostExecute()
+ Изменить
mJSONArr = ob1.getJSONArray("items");
в
mJSONArr = jsonObject.getJSONArray("items");
Также добавьте нулевую проверку перед выполнением любой операции над ним.
@Override
protected void onPostExecute(JSONObject jsonObject) {
try {
mJSONArr = jsonObject.getJSONArray("items");
if(mJSONArr != null)
{
for(int i=0;i<20;i++)
{
ob2 = mJSONArr.getJSONObject(i);
if(ob2 != null)
{
holder+=ob2.getString("title");
}
}
}
if(holder != null && holder.length() > 0)
tv.setText(holder);
else
tv.setText("Error in fetching Data");
pDialog.dismiss();
} catch (JSONException e) {
e.printStackTrace();
tv.setText("Error in fetching Data");
pDialog.dismiss();
}
}