Ошибка ссылки на нулевой объект 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, если json имеет только 9 элементов (0...8), например, и вы пытаетесь получить 10-й элемент (я =9), вы получите эту ошибку, потому что нет допустимого jsonObject

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();
    }
}
Другие вопросы по тегам