title: Android Studio: Parsing Multiple Nested JSON arrays
body: <p>I am working on a project that parses JSON data from the Google Civic API and displays it to the user. First, the data will be displayed in a recycler view, showing the office name, candidate photo, candidate name and candidate party for each person participating in the election. According to the JSON response, the minimum amount of people that can participate in the election is 2 and the maximum is four. Here is what the layout looks like. 
  <a href="https://i.stack.imgur.com/QSDEZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QSDEZ.png" alt="enter image description here"></a></p>
  
  <p>A list of elections will be shown in the recycler view with a brief glimpse of the candidate information. Once the user clicks on a particular election, they will be directed to another activity that shows the full details of the contest. </p>
  
  <p><a href="https://i.stack.imgur.com/aAD8G.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aAD8G.png" alt="enter image description here"></a>
  My first question is how can structure my class. Do I create an object for each candidate, or do I create an object for the entire election. Here is my current implementation for the Elects class. </p>
  
  <pre><code>package com.example.gabe.politicianspulse;
  
  public class Elects {
  private String officeName;
  private String officeType;
  private String officeLevel;
  private String districtName;
  private String candidateName1;
  private String candidateName2;
  private String candidateName3;
  private String candidateName4;
  private String candidateParty1;
  private String candidateParty2;
  private String candidateParty3;
  private String candidateParty4;
  private String candidateURL1;
  private String candidateURL2;
  private String candidateURL3;
  private String candidateURL4;
  private String photoUrl1;
  private String photoUrl2;
  private String photoUrl3;
  private String photoUrl4;
  
  //constructor with all data
  public Elects(String officeName, String officeType, String officeLevel, String districtName, String candidateName1, String candidateName2,
                String candidateName3, String candidateName4, String candidateParty1, String candidateParty2, String candidateParty3,
                String candidateParty4, String candidateURL1, String candidateURL2, String candidateURL3, String candidateURL4,
                String photoUrl1, String photoUrl2, String photoUrl3, String photoUrl4) {
      this.officeName = officeName;
      this.officeType = officeType;
      this.officeLevel = officeLevel;
      this.districtName = districtName;
      this.candidateName1 = candidateName1;
      this.candidateName2 = candidateName2;
      this.candidateName3 = candidateName3;
      this.candidateName4 = candidateName4;
      this.candidateParty1 = candidateParty1;
      this.candidateParty2 = candidateParty2;
      this.candidateParty3 = candidateParty3;
      this.candidateParty4 = candidateParty4;
      this.candidateURL1 = candidateURL1;
      this.candidateURL2 = candidateURL2;
      this.candidateURL3 = candidateURL3;
      this.candidateURL4 = candidateURL4;
      this.photoUrl1 = photoUrl1;
      this.photoUrl2 = photoUrl2;
      this.photoUrl3 = photoUrl3;
      this.photoUrl4 = photoUrl4;
  }
  
  //constructor with 1 candidate
  public Elects(String officeName, String officeType, String officeLevel, String districtName, String candidateName1, String candidateParty1, String candidateURL1, String photoUrl1) {
      this.officeName = officeName;
      this.officeType = officeType;
      this.officeLevel = officeLevel;
      this.districtName = districtName;
      this.candidateName1 = candidateName1;
      this.candidateParty1 = candidateParty1;
      this.candidateURL1 = candidateURL1;
      this.photoUrl1 = photoUrl1;
  }
  
  public Elects(String officeName, String officeType, String officeLevel, String districtName, String candidateName1, String candidateParty1, String candidateURL1) {
      this.officeName = officeName;
      this.officeType = officeType;
      this.officeLevel = officeLevel;
      this.districtName = districtName;
      this.candidateName1 = candidateName1;
      this.candidateParty1 = candidateParty1;
      this.candidateURL1 = candidateURL1;
  }
  
  //constructor with 2 candidates
  public Elects(String officeName, String officeType, String officeLevel, String districtName, String candidateName1, String candidateName2,
                String candidateParty1, String candidateParty2, String candidateURL1, String candidateURL2, String photoUrl1, String photoUrl2) {
      this.officeName = officeName;
      this.officeType = officeType;
      this.officeLevel = officeLevel;
      this.districtName = districtName;
      this.candidateName1 = candidateName1;
      this.candidateName2 = candidateName2;
      this.candidateParty1 = candidateParty1;
      this.candidateParty2 = candidateParty2;
      this.candidateURL1 = candidateURL1;
      this.candidateURL2 = candidateURL2;
      this.photoUrl1 = photoUrl1;
      this.photoUrl2 = photoUrl2;
  }
  
  
  
  //Constructor with no photo data
  public Elects(String officeName, String officeType, String officeLevel, String districtName, String candidateName1, String candidateName2,
                String candidateName3, String candidateName4, String candidateParty1, String candidateParty2, String candidateParty3,
                String candidateParty4, String candidateURL1, String candidateURL2, String candidateURL3, String candidateURL4) {
      this.officeName = officeName;
      this.officeType = officeType;
      this.officeLevel = officeLevel;
      this.districtName = districtName;
      this.candidateName1 = candidateName1;
      this.candidateName2 = candidateName2;
      this.candidateName3 = candidateName3;
      this.candidateName4 = candidateName4;
      this.candidateParty1 = candidateParty1;
      this.candidateParty2 = candidateParty2;
      this.candidateParty3 = candidateParty3;
      this.candidateParty4 = candidateParty4;
      this.candidateURL1 = candidateURL1;
      this.candidateURL2 = candidateURL2;
      this.candidateURL3 = candidateURL3;
      this.candidateURL4 = candidateURL4;
  }
  </code></pre>
  
  <p>Here is a snippet from the JSON response from my url request</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>{
   "contests": [
    {
     "type": "General",
     "office": "US House - District 31",
     "level": [
      "country"
     ],
     "roles": [
      "legislatorLowerBody"
     ],
     "district": {
      "name": "California's 31st congressional district",
      "scope": "congressional",
      "id": "ocd-division/country:us/state:ca/cd:31"
     },
     "candidates": [
      {
       "name": "Pete Aguilar",
       "party": "Democratic",
       "candidateUrl": "http://www.peteaguilar.com/",
       "channels": [
        {
         "type": "Facebook",
         "id": "https://www.facebook.com/PeteAguilarforCongress"
        },
        {
         "type": "Twitter",
         "id": "https://twitter.com/aguilarpete"
        },
        {
         "type": "YouTube",
         "id": "https://www.youtube.com/channel/UCIXCmfuRWrbgdTw257_lxJQ"
        }
       ]
      },
      {
       "name": "Paul Chabot",
       "party": "Republican",
       "candidateUrl": "http://www.paulchabot.com/",
       "channels": [
        {
         "type": "Facebook",
         "id": "https://www.facebook.com/PaulChabotCalifornia"
        },
        {
         "type": "Twitter",
         "id": "https://twitter.com/DrPaulChabot"
        },
        {
         "type": "YouTube",
         "id": "https://www.youtube.com/user/Voteforaveteran"
        }
       ]
      }
     ]
    },
    {
     "type": "General",
     "office": "Governor",
     "level": [
      "administrativeArea1"
     ],
     "roles": [
      "headOfGovernment"
     ],
     "district": {
      "name": "California",
      "scope": "statewide",
      "id": "ocd-division/country:us/state:ca"
     },
     "candidates": [
      {
       "name": "Edmund G. \"Jerry\" Brown",
       "party": "Democratic",
       "channels": [
        {
         "type": "Facebook",
         "id": "https://www.facebook.com/jerrybrown"
        },
        {
         "type": "Twitter",
         "id": "https://twitter.com/JerryBrownGov"
        },
        {
         "type": "GooglePlus",
         "id": "https://plus.google.com/+JerryBrown"
        },
        {
         "type": "YouTube",
         "id": "https://www.youtube.com/user/JerryBrown2010"
        }
       ]
      },
      {
       "name": "Neel Kashkari",
       "party": "Republican",
       "candidateUrl": "http://www.neelkashkari.com/",
       "channels": [
        {
         "type": "Facebook",
         "id": "https://www.facebook.com/neelkashkari"
        },
        {
         "type": "Twitter",
         "id": "https://twitter.com/neelkashkari"
        },
        {
         "type": "GooglePlus",
         "id": "https://plus.google.com/111272745095197246971"
        },
        {
         "type": "YouTube",
         "id": "https://www.youtube.com/channel/UCGhIiUj05N8mlUNeiKbYfsA"
        }
       ]
      }
     ]
    }
    
    
      
    </code></pre>
  </div>
  </div>
  </p>
  
  <p>Right now, my parsing method only creates an object for a single candidate because I'm not sure how to parse data for all candidates, but before solving this problem, I would like to tackle the immediate issue. When the activity tries to run, an empty activity is displayed with nothing populating the recycler view. The log cat points to my getData() function saying there is no value for "district". The district and candidate JSON arrays are nested arrays within the "contests" array. Could  this be why the value for district is not found? How can I navigate through the district and candidates JSON arrays?</p>
  
  <p>getData(): </p>
  
  <pre><code> private void getData(){
      final ProgressDialog progressDialog = new ProgressDialog(this);
      progressDialog.setMessage("Loading...");
      progressDialog.show();
  
      StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener&lt;String&gt;() {
          @Override
          public void onResponse(String response) {
              progressDialog.dismiss();
              try {
                  JSONObject jsonObject = new JSONObject(response);
                  //Three arrays for each JSON array
                  JSONArray contestsArray = jsonObject.getJSONArray("contests");
                  JSONArray districtArray = jsonObject.getJSONArray("district");
                  JSONArray candidatesArray = jsonObject.getJSONArray("candidates");
                  for (int i = 0; i &lt; contestsArray.length(); i++) {
                      JSONObject jsonContests = contestsArray.getJSONObject(i);
                      JSONObject jsonDistrict = districtArray.getJSONObject(i);
                      JSONObject jsonCandidates = candidatesArray.getJSONObject(i);
                      if(jsonCandidates.has("photoUrl")){         //Create case for no PhotoUrl
                          Elects x = new Elects(jsonContests.getString("office"),
                                  jsonContests.getString("type"),
                                  jsonContests.getString("level"),
                                  jsonDistrict.getString("name"),
                                  jsonCandidates.getString("name"),
                                  jsonCandidates.getString("party"),
                                  jsonCandidates.getString("candidateUrl"),
                                  jsonCandidates.getString("photoUrl"));
                          electsList.add(x);
                      } else{
                          Elects a = new Elects(jsonContests.getString("office"),
                                  jsonContests.getString("type"),
                                  jsonContests.getString("level"),
                                  jsonDistrict.getString("name"),
                                  jsonCandidates.getString("name"),
                                  jsonCandidates.getString("party"),
                                  jsonCandidates.getString("candidateUrl"));
                          electsList.add(a);
                      }
                  }
                  adapter = new ElectsRvAdapter(getApplicationContext(), electsList);
                  myrv.setAdapter(adapter);
              } catch (JSONException e) {
                  e.printStackTrace();
              }
  
          }
      }, new Response.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError error) {
              Log.e("Volley", error.toString());
              progressDialog.dismiss();
          }
      });
      RequestQueue requestQueue = Volley.newRequestQueue(this);
      requestQueue.add(stringRequest);
  }
  </code></pre>
  
  <p>}</p>
  
  <p>Logcat Error:</p>
  
  <p><a href="https://i.stack.imgur.com/upydN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/upydN.png" alt="enter image description here"></a></p>
  
  <p>Other relevant code:</p>
  
  <p>ElectsRvAdapter: Recycler view adapter for the Elect class</p>
  
  <pre><code>public class ElectsRvAdapter extends 
  RecyclerView.Adapter&lt;ElectsRvAdapter.MyViewHolder&gt; {
  
  private Context context;
  private List&lt;Elects&gt; electsList;
  
  public ElectsRvAdapter(){
  
  }
  
  public ElectsRvAdapter(Context context, List&lt;Elects&gt; electsList){
      this.context = context;
      this.electsList = electsList;
  }
  
  @NonNull
  @Override
  public ElectsRvAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
      View v;
      LayoutInflater mInflater = LayoutInflater.from(context);
      v = mInflater.inflate(R.layout.election_card, viewGroup, false);
      final MyViewHolder viewHolder = new MyViewHolder(v);
      viewHolder.electionContainer.setOnClickListener(new View.OnClickListener(){
          @Override
          public void onClick(View view){
              Intent i = new Intent(context, SingleElection.class);
              i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
              i.putExtra("office", electsList.get(viewHolder.getAdapterPosition()).getOfficeName());
              i.putExtra("type", electsList.get(viewHolder.getAdapterPosition()).getOfficeType());
              i.putExtra("level", electsList.get(viewHolder.getAdapterPosition()).getOfficeLevel());
              i.putExtra("name", electsList.get(viewHolder.getAdapterPosition()).getDistrictName());
              i.putExtra("name", electsList.get(viewHolder.getAdapterPosition()).getCandidateName1());
              i.putExtra("name", electsList.get(viewHolder.getAdapterPosition()).getCandidateName2());
              i.putExtra("name", electsList.get(viewHolder.getAdapterPosition()).getCandidateName3());
              i.putExtra("name", electsList.get(viewHolder.getAdapterPosition()).getCandidateName4());
              i.putExtra("party", electsList.get(viewHolder.getAdapterPosition()).getCandidateParty1());
              i.putExtra("party", electsList.get(viewHolder.getAdapterPosition()).getCandidateParty2());
              i.putExtra("party", electsList.get(viewHolder.getAdapterPosition()).getCandidateParty3());
              i.putExtra("party", electsList.get(viewHolder.getAdapterPosition()).getCandidateParty4());
              i.putExtra("candidateUrl", electsList.get(viewHolder.getAdapterPosition()).getCandidateURL1());
              i.putExtra("candidateUrl", electsList.get(viewHolder.getAdapterPosition()).getCandidateURL2());
              i.putExtra("candidateUrl", electsList.get(viewHolder.getAdapterPosition()).getCandidateURL3());
              i.putExtra("candidateUrl", electsList.get(viewHolder.getAdapterPosition()).getCandidateURL4());
              i.putExtra("photoUrl", electsList.get(viewHolder.getAdapterPosition()).getPhotoUrl1());
              i.putExtra("photoUrl", electsList.get(viewHolder.getAdapterPosition()).getPhotoUrl2());
              i.putExtra("photoUrl", electsList.get(viewHolder.getAdapterPosition()).getPhotoUrl3());
              i.putExtra("photoUrl", electsList.get(viewHolder.getAdapterPosition()).getPhotoUrl4());
  
              context.startActivity(i);
          }
      });
      return viewHolder;
  }
  
  @Override
  public void onBindViewHolder(@NonNull ElectsRvAdapter.MyViewHolder myViewHolder, int i) {
      myViewHolder.officeName.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateName1.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateName2.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateName3.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateName4.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateParty1.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateParty2.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateParty3.setText(electsList.get(i).getOfficeName());
      myViewHolder.candidateParty4.setText(electsList.get(i).getOfficeName());
      myViewHolder.officeName.setText(electsList.get(i).getOfficeName());
      myViewHolder.officeName.setText(electsList.get(i).getOfficeName());
  }
  
  @Override
  public int getItemCount() {
      return electsList.size();
  }
  
  public static class MyViewHolder extends RecyclerView.ViewHolder{
      TextView officeName, candidateName1, candidateName2, candidateName3,
              candidateName4, candidateParty1, candidateParty2,
              candidateParty3, candidateParty4;
      ImageView photoUrl1, photoUrl2, photoUrl3, photoUrl4;
      LinearLayout electionContainer;
      public MyViewHolder(View itemView){
          super(itemView);
          officeName = itemView.findViewById(R.id.office_name);
          candidateName1 = itemView.findViewById(R.id.candidate_name1);
          candidateName2 = itemView.findViewById(R.id.candidate_name2);
          candidateName3 = itemView.findViewById(R.id.candidate_name3);
          candidateName4 = itemView.findViewById(R.id.candidate_name4);
          candidateParty1 = itemView.findViewById(R.id.candidate_party1);
          candidateParty2 = itemView.findViewById(R.id.candidate_party2);
          candidateParty3 = itemView.findViewById(R.id.candidate_party3);
          candidateParty4 = itemView.findViewById(R.id.candidate_party4);
          photoUrl1 = itemView.findViewById(R.id.photo_url1);
          photoUrl2 = itemView.findViewById(R.id.photo_url2);
          photoUrl3 = itemView.findViewById(R.id.photo_url3);
          photoUrl4 = itemView.findViewById(R.id.photo_url4);
          electionContainer = itemView.findViewById(R.id.elections_container);
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>SingleElection: Activity that displays more detailed information about the election</p>
  
  <pre><code>public class SingleElection extends AppCompatActivity {
  
  private List&lt;Elects&gt; electsList;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_single_election);
  
      electsList = new ArrayList&lt;&gt;();
  
      //recieve data
      String name = getIntent().getExtras().getString("office");
      String type = getIntent().getExtras().getString("type");
      String level = getIntent().getExtras().getString("level");
      String dName = getIntent().getExtras().getString("name");
      String cName1 = getIntent().getExtras().getString("name");
      String cName2 = getIntent().getExtras().getString("name");
      String cName3 = getIntent().getExtras().getString("name");
      String cName4 = getIntent().getExtras().getString("name");
      String cParty1 = getIntent().getExtras().getString("party");
      String cParty2 = getIntent().getExtras().getString("party");
      String cParty3 = getIntent().getExtras().getString("party");
      String cParty4 = getIntent().getExtras().getString("party");
      String cUrl1 = getIntent().getExtras().getString("candidateUrl");
      String cUrl2 = getIntent().getExtras().getString("candidateUrl");
      String cUrl3 = getIntent().getExtras().getString("candidateUrl");
      String cUrl4 = getIntent().getExtras().getString("candidateUrl");
      String photoUrl1 = getIntent().getExtras().getString("photoUrl");
      String photoUrl2 = getIntent().getExtras().getString("photoUrl");
      String photoUrl3 = getIntent().getExtras().getString("photoUrl");
      String photoUrl4 = getIntent().getExtras().getString("photoUrl");
  
      //Initialize Views
      TextView nameTv = findViewById(R.id.office);
      TextView typeTv = findViewById(R.id.type);
      TextView levelTv = findViewById(R.id.level);
      TextView dNameTv = findViewById(R.id.district_name);
      TextView cNameTv1 = findViewById(R.id.c_name1);
      TextView cNameTv2 = findViewById(R.id.c_name2);
      TextView cNameTv3 = findViewById(R.id.c_name3);
      TextView cNameTv4 = findViewById(R.id.c_name4);
      TextView cPartyTv1 = findViewById(R.id.c_party1);
      TextView cPartyTv2 = findViewById(R.id.c_party2);
      TextView cPartyTv3 = findViewById(R.id.c_party3);
      TextView cPartyTv4 = findViewById(R.id.c_party4);
      TextView cUrlTv1 = findViewById(R.id.c_url1);
      TextView cUrlTv2 = findViewById(R.id.c_url2);
      TextView cUrlTv3 = findViewById(R.id.c_url3);
      TextView cUrlTv4 = findViewById(R.id.c_url4);
      ImageView photoUrlTv1 = findViewById(R.id.photo1);
      ImageView photoUrlTv2 = findViewById(R.id.photo2);
      ImageView photoUrlTv3 = findViewById(R.id.photo3);
      ImageView photoUrlTv4 = findViewById(R.id.photo4);
  
      //set string values to each view
      nameTv.setText(name);
      typeTv.setText(type);
      levelTv.setText(level);
      dNameTv.setText(dName);
      cNameTv1.setText(name);
      cNameTv2.setText(name);
      cNameTv3.setText(name);
      cNameTv4.setText(name);
      cPartyTv1.setText(name);
      cPartyTv2.setText(name);
      cPartyTv3.setText(name);
      cPartyTv4.setText(name);
      cUrlTv1.setText(name);
      cUrlTv2.setText(name);
      cUrlTv3.setText(name);
      cUrlTv4.setText(name);
  
      //set image
      Picasso.get()
              .load(photoUrl1)
              .centerCrop()
              .transform(new CircleTransform(50, 0))
              .fit()
              .into(photoUrlTv1);
      Picasso.get()
              .load(photoUrl2)
              .centerCrop()
              .transform(new CircleTransform(50, 0))
              .fit()
              .into(photoUrlTv2);
      Picasso.get()
              .load(photoUrl3)
              .centerCrop()
              .transform(new CircleTransform(50, 0))
              .fit()
              .into(photoUrlTv3);
      Picasso.get()
              .load(photoUrl4)
              .centerCrop()
              .transform(new CircleTransform(50, 0))
              .fit()
              .into(photoUrlTv4);
  
  }
  </code></pre>
  
  <p>}</p>
  
  <p>To sum up:</p>
  
  <ol>
  <li>How can I alter rmy getData() function to properly iterate through nested JSON arrays.</li>
  <li>How should I structure my Elects class to receive the JSON data in the easiest, most efficient way?</li>
  </ol>
  
  <p>Thanks Much! If you need any more code, let me know. </p>