0

I have a jsonArray which I want to parse in my android app.

The array:-

[
   {
      "id": 96905,
      "category": "topup",
      "detail": "Full talktime of Rs.55 + 1 local airtel SMS free for 1 day",
      "price": 55,
      "keywords": "topup",
      "updated": "2016-01-07 00:16:23.0",
      "validity": "7 days",
      "service": "Airtel",
      "sourceUri": "https://pay.airtel.com/online-payments/recharge.jsp",
      "circle": "Assam",
      "talktime": 55
   },

   {
      "id": 90397,
      "category": "topup",
      "price": 510,
      "keywords": "topup",
      "updated": "2016-01-07 00:16:23.0",
      "service": "Airtel",
      "sourceUri": "https://pay.airtel.com/online-payments/recharge.jsp",
      "circle": "Assam",
      "talktime": 520
   },
   {
      "id": 90399,
      "category": "topup",
      "price": 1000,
      "keywords": "topup",
      "updated": "2016-01-07 00:16:23.0",
      "service": "Airtel",
      "sourceUri": "https://pay.airtel.com/online-payments/recharge.jsp",
      "circle": "Assam",
      "talktime": 1020
   }]

My android Code:-

Asynctask:-

private class DownloadJSON extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgressDialog = new ProgressDialog(MainActivity.this);
            mProgressDialog.setTitle("Android JSON Parse Tutorial");
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            // Create an array
            arraylist = new ArrayList<HashMap<String, String>>();
            try {
                JSONObject jo;
               JSONArray ja2 = JSONfunctions.getJSONfromURL("http://app.ireff.in:9090/IreffWeb/android?service=airtel&circle=assam");

                for (int i = 0; i < ja2.length(); i++) {
                    HashMap<String, String> map = new HashMap<String, String>();
                    jo = ja2.getJSONObject(i);   
                    map.put("rank", jo.getString("price"));
                    map.put("country", jo.getString("validity"));
                    map.put("population", jo.getString("talktime"));
                    arraylist.add(map);
                }
            } catch (JSONException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void args) {
            listview = (ListView) findViewById(R.id.listview);
            adapter = new ListViewAdapter(MainActivity.this, arraylist);
            listview.setAdapter(adapter);
            mProgressDialog.dismiss();
        }
    }

JsonFunctions.java

public class JSONfunctions {

    public static JSONArray getJSONfromURL(String url) {
        InputStream is = null;
        String result = "";
        JSONArray jArray = null;

        // Download JSON data from URL
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();

        } catch (Exception e) {
            Log.e("log_tag", "Error in http connection " + e.toString());
        }

        // Convert response to string
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            result = sb.toString();
        } catch (Exception e) {
            Log.e("log_tag", "Error converting result " + e.toString());
        }

        try {

            jArray = new JSONArray(result);
        } catch (JSONException e) {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }

        return jArray;
    }
}

The error I get:-

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int org.json.JSONArray.length()' on a null object reference
at com.androidbegin.jsonparsetutorial.MainActivity$DownloadJSON.doInBackground(MainActivity.java:67)
at com.androidbegin.jsonparsetutorial.MainActivity$DownloadJSON.doInBackground(MainActivity.java:39)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:818) 

The json is hosted here

I was following this tutorial for learning json parsing, but this tutorial uses jsonObject and I am not able to parse the json array.

Not a duplicate to this :-Sending and Parsing JSON Objects or this How to parse this JSON Array in android?

Community
  • 1
  • 1
Sleez
  • 107
  • 1
  • 10
  • 3
    You can learn about NullPointerException => http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it – Neige Jan 07 '16 at 09:52
  • validity is not in second object – Pavya Jan 07 '16 at 09:52
  • Also httpclient is deprecated. Use httpurlconnection instead – Raghunandan Jan 07 '16 at 09:55
  • I am able to parse the json sucessfully if i supply it as a local string, but i am facing the issue when trying to download it from the internet, so validity works – Sleez Jan 07 '16 at 09:56
  • @Raghunandan sure, I will do that, but can you please say at present what is wrong – Sleez Jan 07 '16 at 09:57
  • @Sleez Your json array is null. Log what you get from server – Raghunandan Jan 07 '16 at 10:00
  • 3
    Are you check this value ``result = sb.toString();`` , it not null ??? – Danh DC Jan 07 '16 at 10:01
  • @DanhDC yes it is null wierdly, I do not know why, The original link given by the tutorial does not give null – Sleez Jan 07 '16 at 10:02
  • Please change ``HttpPost httppost = new HttpPost(url);`` to ``HttpGet httpGet = new HttpGet(url);`` – Danh DC Jan 07 '16 at 10:05
  • This tutorial really helps you and most advanced tutorial for future development. http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html – Danial Hussain Jan 07 '16 at 10:07
  • Here JSONArray ja2 = JSONfunctions.getJSONfromURL("http://app.ireff.in:9090/IreffWeb/android?service=airtel&circle=assam"); whats the value for ja2 you are getting?it could be null. – Mahalakshmi Jan 07 '16 at 10:08
  • @DanhDC I am getting different json, But tell me, why does the original link given in the tutorial work but not this link, i mean i am getting different json values compared on PC and mobile. – Sleez Jan 07 '16 at 10:11
  • @Sleez the result of tutorial have format ``worldpopulation: [-json array]`` , it have **JsonArray Name** is **worldpopulation**. And look again tutorial code, it use ``jsonarray = jsonobject.getJSONArray("worldpopulation"); `` – Danh DC Jan 07 '16 at 10:16
  • I am getting Unauthorized server access when I am trying to use HttpGet – Sleez Jan 07 '16 at 10:20
  • If use **POST** method, you can add new string to result like : ``{ - jsonArrayName: put your arr result here }`` , then use same tutorial ``JSONObject ob= new JSONObject(result); jArray = ob.getJSONArray("jsonArrayName");`` – Danh DC Jan 07 '16 at 10:24
  • but the original tutorial is using post method itself and it is able to retrive the json, why is the same not possibe with the new link ? – Sleez Jan 07 '16 at 10:26
  • About **Unauthorized** exception, you can look around http://stackoverflow.com/questions/5283996/android-httpclient-authentication-always-returns-401-code – Danh DC Jan 07 '16 at 10:26
  • i agree to Danh..comment above,still hv described in detail again - wrap the overall jsonarray into jsonobject at server end then from jsonobject fetch the jsonarray.ex: {"jsonListName":["id":"value1","category":"value2"]} JSONObject jo = JSONfunctions.getJSONfromURL("http://app.ireff.in:9090/IreffWeb/android?service=airtel&circle=assam"); if(jo !=null){ JSONArray ja2=jo.getJSONArray("jsonListName"); if(ja2!=null){ // iterate parse json and fetch value for id and category here } } – Mahalakshmi Jan 07 '16 at 10:27
  • @DanhDC The unauthorized exception is comming only if i used HttpGet not for HttpPost – Sleez Jan 07 '16 at 10:29
  • @Sleez check your host **http://app.ireff.in:9090** , maybe it need some permission, so you can add some scope ``AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT`` – Danh DC Jan 07 '16 at 10:33
  • Sure, But is the permission to view from PC(which i am able to do without having any permission) vs parsing json from android is different ? – Sleez Jan 07 '16 at 10:35
  • 1
    @Sleez look around stackoverflow with key **android httpclient unauthorized** , i think have many solution can help you – Danh DC Jan 07 '16 at 10:39
  • whats the service used at back end? if using wcf then this could help //server configuration [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/android?service={strser}&circle={strc}")] string android(string USRID, string PWD); //method declaration public string android(string service,string circle){ string strser = service.Trim(); string User_IMEINo = strIMEI.Trim(); return "";} – Mahalakshmi Jan 07 '16 at 10:54
  • Please clarify on point the null pointer is? – akash yadav Jan 07 '16 at 11:07

3 Answers3

2

Let me offer an alternate solution (of sorts). A much simpler version of your existing code would be:

Updated code:

private class DownloadJSON extends AsyncTask<Void, Void, Void> {

    ProgressDialog mProgressDialog;

    ArrayList<HashMap<String, String>> arraylist = new ArrayList<>();

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        mProgressDialog = new ProgressDialog(TestListActivity.this);
        mProgressDialog.setTitle("Android JSON Parse Tutorial");
        mProgressDialog.setMessage("Loading...");
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {

        String url = "http://app.ireff.in:9090/IreffWeb/android?service=airtel&circle=assam";

        OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setRetryOnConnectionFailure(true);

        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);

        try {
            Response response = call.execute();
            String strResult = response.body().string();
            JSONArray JARoot = new JSONArray(strResult);

            for (int i = 0; i < JARoot.length(); i++) {
                JSONObject JORoot = JARoot.getJSONObject(i);

                HashMap<String, String> map = new HashMap<>();

                if (JORoot.has("category") && JORoot.getString("category").equals("topup"))   {

                    if (JORoot.has("id")) {
                        map.put("id", JORoot.getString("id"));
                    }

                    if (JORoot.has("category")) {
                        map.put("category", JORoot.getString("category"));
                    }

                    if (JORoot.has("detail")) {
                        map.put("detail", JORoot.getString("detail"));
                    } else {
                        map.put("detail", null);
                    }

                    if (JORoot.has("price")) {
                        map.put("price", JORoot.getString("price"));
                    }

                    /** ADD THE COLLECTED DATA TO THE ARRAY LIST **/
                    arraylist.add(map); /* THE DATA WILL ONLY BE ADDED IF THE CATEGORY = "topup" */
                }
            }
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        ListView testList = (ListView) findViewById(R.id.testList);
        TestListAdapter adapter = new TestListAdapter(TestListActivity.this, arraylist);
        testList.setAdapter(adapter);

        mProgressDialog.dismiss();
    }
}

private class TestListAdapter extends BaseAdapter {

    Activity activity;

    // LAYOUTINFLATER TO USE A CUSTOM LAYOUT
    LayoutInflater inflater = null;

    // ARRAYLIST TO GET DATA FROM THE ACTIVITY
    ArrayList<HashMap<String, String>> arrItem;

    public TestListAdapter(Activity activity, ArrayList<HashMap<String, String>> arrItem) {

        this.activity = activity;

        // CAST THE CONTENTS OF THE ARRAYLIST IN THE METHOD TO THE LOCAL INSTANCE
        this.arrItem = arrItem;

        // INSTANTIATE THE LAYOUTINFLATER
        inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return arrItem.size();
    }

    @Override
    public Object getItem(int position) {
        return arrItem.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        // A VIEWHOLDER INSTANCE
        ViewHolder holder;

        // CAST THE CONVERTVIEW IN A VIEW INSTANCE
        View vi = convertView;

        // CHECK CONVERTVIEW STATUS
        if (convertView == null)    {
            // CAST THE CONVERTVIEW INTO THE VIEW INSTANCE vi
            vi = inflater.inflate(R.layout.test_item, null);

            // INSTANTIATE THE VIEWHOLDER INSTANCE
            holder = new ViewHolder();

            /*****  CAST THE LAYOUT ELEMENTS    *****/

            /* TOP (PRIMARY) ELEMENTS */
            holder.txtPrice = (TextView) vi.findViewById(R.id.txtPrice);
            holder.txtDetail = (TextView) vi.findViewById(R.id.txtDetail);

            // SET THE TAG TO "vi"
            vi.setTag(holder);
        } else {
            // CAST THE VIEWHOLDER INSTANCE
            holder = (ViewHolder) vi.getTag();
        }

        if (arrItem.get(position).get("price") != null)    {
            String strPrice = arrItem.get(position).get("price");
            holder.txtPrice.setText("PRICE:  " + strPrice);
        }

        if (arrItem.get(position).get("detail") != null)   {
            String strDetail = arrItem.get(position).get("detail");
            holder.txtDetail.setText("DETAIL: " + strDetail);
        } else {
            holder.txtDetail.setText("DETAIL: NA");
        }

        return vi;
    }

    private class ViewHolder    {

        /* TOP (PRIMARY) ELEMENTS */
        TextView txtPrice;
        TextView txtDetail;
    }
}

For the sake of completeness, I am also including the code for the adapter. It is a simple implementation. Do clean it up / optimize it / customize as per your requirement.

  1. This piece of code has been tested prior to being posted (see screenshot of Logs at the bottom)
  2. This uses the OkHttp library. Add this compile statement to the dependencies section of the module's gradle file: compile 'com.squareup.okhttp:okhttp:2.5.0'. Check the link for an updated version.
  3. The example code uses if statements considering that not every record has the same set of nodes.

enter image description here

enter image description here

Siddharth Lele
  • 27,623
  • 15
  • 98
  • 151
  • what is okhttp ? a dependency ? – Sleez Jan 07 '16 at 11:23
  • @Sleez: Correct. It's a library by [Square](http://square.github.io/). Just add `compile 'com.squareup.okhttp:okhttp:2.5.0'` to your Gradle file, sync it and you'll be all set. – Siddharth Lele Jan 07 '16 at 11:26
  • Cannot resolve methods okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS); okHttpClient.setReadTimeout(30, TimeUnit.SECONDS); okHttpClient.setRetryOnConnectionFailure(true); – Sleez Jan 07 '16 at 11:27
  • @Sleez you will need to add the `compile...` to your gradle mentioned in my earlier comment. – Siddharth Lele Jan 07 '16 at 11:29
  • yes yes, i have added the file, only those 3 methods have problem – Sleez Jan 07 '16 at 11:31
  • 1
    @Sleez: Use the version in the updated and post. The 3.0.0 might have changed something. Change that bit to `compile 'com.squareup.okhttp:okhttp:2.5.0'` – Siddharth Lele Jan 07 '16 at 11:33
  • thanks for ur help, I feel this solution works as i can see my logs giving output, but it is crashing as i am trying to populate my list, so can you please tell me a solution accordingly ? More specifically this error java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference at com.androidbegin.jsonparsetutorial.ListViewAdapter.getCount(ListViewAdapter.java:34) – Sleez Jan 07 '16 at 11:38
  • 1
    @Sleez: Give me a couple of minutes while I cook up a full working solution. – Siddharth Lele Jan 07 '16 at 12:03
  • Super thanks, much thanks, billion thanks. 2 questions which rom is that and what are the advantages of okhttp over normal http method – Sleez Jan 07 '16 at 13:20
  • 1
    @Sleez: You are welcome. For your first question, that's actually a Xiaomi Redmi 2 Prime with the MIUI ROM on it. And second, OkHttp is faster as against the standard HTTP. It has compression, low latency and several of the good things. I have always preferred it over stock HTTP for a couple of years now. – Siddharth Lele Jan 07 '16 at 13:53
  • Dhanyavaad IceMAN :-) – Sleez Jan 07 '16 at 14:15
  • @Sleez Glad to have helped :-) – Siddharth Lele Jan 07 '16 at 14:23
  • One last question, as you can see the json has many objects, i want to display/parse only those objects which has "category" as "topup", how to do that? – Sleez Jan 07 '16 at 14:26
  • @Sleez: That simple enough. Check the update in the post. Specifically, the first `if` statement at the start of the `for` loop. ;-) – Siddharth Lele Jan 07 '16 at 14:32
  • 1
    Dude, this question should be given oscar, i was using if(JORoot.getString("category")=="topup"), nvm, we all learn, dhanyavaad so much – Sleez Jan 07 '16 at 14:38
1
jsonResponse="";
for(int i = 0; i<response.length(); i++) {
    JSONObject person = (JSONObject) response.get(i);

    String id = person.getString("id");
    String category = person.getString("category");
}
Siddharth Lele
  • 27,623
  • 15
  • 98
  • 151
sudheer
  • 19
  • 2
1

You BufferReader is not working as expected in your class JSONfunctions , do some changes in your class and it should looks like

JSONfunctions.java

public class JSONfunctions {

public static JSONArray getJSONfromURL(String url) {
    InputStream is = null;
    String result = "";
    JSONArray jArray = null;

    // Download JSON data from URL
    try {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(url);
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();
        is = entity.getContent();

    } catch (Exception e) {
        Log.e("log_tag", "Error in http connection " + e.toString());
    }


       StringBuffer sb = new StringBuffer("");
    try {
        URL urls = new URL(url);
        URLConnection urlConnection;
        urlConnection = urls.openConnection();
        InputStream in = urlConnection.getInputStream();
        BufferedReader br=new BufferedReader(new InputStreamReader(in));
         String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            System.out.println(sb);
            result=sb.toString();
    } catch (IOException e) {}
      catch (Exception e) {}
    try {

        jArray = new JSONArray(result);
    } catch (JSONException e) {
        Log.e("log_tag", "Error parsing data " + e.toString());
    }

    return jArray;
   }
  }

and to avoid Exception check if JSONArray is not null then only it goes to run for loop like this :

 JSONArray ja2 =   JSONfunctions.getJSONfromURL("http://app.ireff.in:9090/IreffWeb/android?  service=airtel&circle=assam");
 if(ja2!=null)
            for (int i = 0; i < ja2.length(); i++) {}
Kapil Rajput
  • 11,429
  • 9
  • 50
  • 65
  • what is the difference between my JsonFunctions class and your class ? It worked...I am checking everything now – Sleez Jan 07 '16 at 11:03
  • @Sleez i think your `is = entity.getContent();` returning blank or null that's why your BufferedReader cant read blank inputStream – Kapil Rajput Jan 07 '16 at 11:07
  • It is showing only 4 json values, not all json values – Sleez Jan 07 '16 at 11:09
  • Ok, i got it, there is a field not available in All places, Thanks, it fixed my code :-) – Sleez Jan 07 '16 at 11:20