JSON解析器java.lang.NullPointerException

时间:2016-05-21 19:59:25

标签: android json listview android-asynctask

我收到此错误,尝试使用ListView构建JSON解析器。 我尝试使用另一个JSON源代码,它可以工作,但是这个链接崩溃了: http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson

我喜欢一些帮助:D

错误:

05-21 20:53:32.871 2509-2606/com.ikeres.app.professorearthquake     W/System.err: org.json.JSONException: End of input at character 0 of 
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake    W/System.err:     at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONTokener.nextValue(JSONTokener.java:97)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:156)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:173)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at    com.ikeres.app.professorearthquake.MainActivity.ParseJSON(MainActivity.java:102)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at   com.ikeres.app.professorearthquake.MainActivity.access$200(MainActivity.java:19)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  com.ikeres.app.professorearthquake.MainActivity$GetTerremotos.doInBackground(Mai nActivity.java:70)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  com.ikeres.app.professorearthquake.MainActivity$GetTerremotos.doInBackground(Mai nActivity.java:44)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:         at java.lang.Thread.run(Thread.java:818)

以下是MainActivity:

public class MainActivity extends ListActivity {

// URL to get contacts JSON
private static String url = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson";

// JSON Node names
private static final String TAG_FEATURES = "features";
private static final String TAG_PROPERTIES = "properties";
private static final String TAG_LUGAR = "lugar";
private static final String TAG_MAGNITUD = "magnitud";
private static final String TAG_HORA = "hora";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Calling async task to get json
    new GetTerremotos().execute();
}

/**
 * Async task class to get json by making HTTP call
 */
private class GetTerremotos extends AsyncTask<Void, Void, Void> {

    // Hashmap for ListView
    ArrayList<HashMap<String, String>> terremotostList;
    ProgressDialog pDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Please wait...");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        // Creating service handler class instance
        WebRequest webreq = new WebRequest();

        // Making a request to url and getting response
        String jsonStr = webreq.makeWebServiceCall(url, WebRequest.GET);

        Log.d("Response: ", "> " + jsonStr);

        terremotostList = ParseJSON(jsonStr);

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (pDialog.isShowing())
            pDialog.dismiss();
        /**
         * Updating parsed JSON data into ListView
         * */
        ListAdapter adapter = new SimpleAdapter(
                MainActivity.this, terremotostList,
                R.layout.list_item, new String[]{TAG_LUGAR, TAG_MAGNITUD,
                TAG_HORA}, new int[]{R.id.name,
                R.id.email, R.id.mobile});

        setListAdapter(adapter);
    }

}

private ArrayList<HashMap<String, String>> ParseJSON(String json) {
    if (json != null) {
        try {
            // Hashmap for ListView
            ArrayList<HashMap<String, String>> studentList = new ArrayList<HashMap<String, String>>();

            JSONObject jsonObj = new JSONObject(json);

            // Getting JSON Array node
            JSONArray terremotos = jsonObj.getJSONArray(TAG_FEATURES);

            // looping through All HeartQuakes
            for (int i = 0; i < terremotos.length(); i++) {
                JSONObject c = terremotos.getJSONObject(i);




                // Properties node is JSON Object
                JSONObject properties = c.getJSONObject(TAG_PROPERTIES);
                String lugar = properties.getString(TAG_LUGAR);
                String magnitud = properties.getString(TAG_MAGNITUD);
                String hora = properties.getString(TAG_HORA);

                // tmp hashmap for single hq
                HashMap<String, String> oterremoto = new HashMap<String, String>();

                // adding each child node to HashMap key => value
                oterremoto.put(TAG_LUGAR, lugar);
                oterremoto.put(TAG_MAGNITUD, magnitud);
                oterremoto.put(TAG_HORA, hora);


                // adding student to hq list
                studentList.add(oterremoto);
            }
            return studentList;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    } else {
        Log.e("ServiceHandler", "Couldn't get any data from the url");
        return null;
    }
}

}

WebRequest类:

public class WebRequest {

static String response = null;
public final static int GET = 1;
public final static int POST = 2;

//Constructor with no parameter
public WebRequest() {

}

/**
 * Making web service call
 *
 * @url - url to make request
 * @requestmethod - http request method
 */
public String makeWebServiceCall(String url, int requestmethod) {
    return this.makeWebServiceCall(url, requestmethod, null);
}

/**
 * Making service call
 *
 * @url - url to make request
 * @requestmethod - http request method
 * @params - http request params
 */
public String makeWebServiceCall(String urladdress, int requestmethod,
                                 HashMap<String, String> params) {
    URL url;
    String response = "";
    try {
        url = new URL(urladdress);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(15000);
        conn.setConnectTimeout(15000);
        conn.setDoInput(true);
        conn.setDoOutput(true);

        if (requestmethod == POST) {
            conn.setRequestMethod("POST");
        } else if (requestmethod == GET) {
            conn.setRequestMethod("GET");
        }

        if (params != null) {
            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));

            StringBuilder result = new StringBuilder();
            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first)
                    first = false;
                else
                    result.append("&");

                result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                result.append("=");
                result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            }

            writer.write(result.toString());

            writer.flush();
            writer.close();
            os.close();
        }

        int responseCode = conn.getResponseCode();

        if (responseCode == HttpsURLConnection.HTTP_OK) {
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((line = br.readLine()) != null) {
                response += line;
            }
        } else {
            response = "";
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return response;
}

}

2 个答案:

答案 0 :(得分:0)

解析json时需要检查字段是否存在。您的代码在此行失败:

String lugar = properties.getString(TAG_LUGAR);

因为返回的json中没有这样的字段lugar。所以这一行引发了一个异常,这个代码被捕获了:

catch (JSONException e) {
        e.printStackTrace();
        return null;
    }

并返回NULL。然后,您正在创建一个适配器并传递一个空对象:

ListAdapter adapter = new SimpleAdapter(
            MainActivity.this, terremotostList,
            R.layout.list_item, new String[]{TAG_LUGAR, TAG_MAGNITUD,
            TAG_HORA}, new int[]{R.id.name,
            R.id.email, R.id.mobile});

terremotostList为空)

最后,您的适配器无法尝试访问列表中的getCount方法,该方法为null。

如何解决这个问题?您应该在获取其值之前检查字段是否存在:

String lugar = properties.has(TAG_LUGAR) ? properties.getString(TAG_LUGAR) : null;

或只使用optString方法,如果字段不存在则不会抛出异常:

String lugar = properties.optString(TAG_LUGAR);

答案 1 :(得分:0)

终于明白了。从WebRequest类中删除以下行:

    conn.setDoInput(true);
    conn.setDoOutput(true);

conn.setRequestMethod("GET");之后添加以下内容:

conn.connect();

现在,您从JSON中获得API。之后你的应用程序将不会显示任何内容。那是因为你的标签都是西班牙语,而API是英文的,所以改变:

private static final String TAG_LUGAR = "lugar";
private static final String TAG_MAGNITUD = "magnitud";
private static final String TAG_HORA = "hora";

为:

private static final String TAG_LUGAR = "place";
private static final String TAG_MAGNITUD = "mag";
private static final String TAG_HORA = "time";

在这些变化之后它会起作用。