Android Studio: Parsing Multiple Nested JSON arrays












0















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.
enter image description here



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.



enter image description here
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.



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;
}


Here is a snippet from the JSON response from my url request






{
"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"
}
]
}
]
}








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?



getData():



 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<String>() {
@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 < 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);
}


}



Logcat Error:



enter image description here



Other relevant code:



ElectsRvAdapter: Recycler view adapter for the Elect class



public class ElectsRvAdapter extends 
RecyclerView.Adapter<ElectsRvAdapter.MyViewHolder> {

private Context context;
private List<Elects> electsList;

public ElectsRvAdapter(){

}

public ElectsRvAdapter(Context context, List<Elects> 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);
}
}


}



SingleElection: Activity that displays more detailed information about the election



public class SingleElection extends AppCompatActivity {

private List<Elects> electsList;

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

electsList = new ArrayList<>();

//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);

}


}



To sum up:




  1. How can I alter rmy getData() function to properly iterate through nested JSON arrays.

  2. How should I structure my Elects class to receive the JSON data in the easiest, most efficient way?


Thanks Much! If you need any more code, let me know.










share|improve this question





























    0















    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.
    enter image description here



    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.



    enter image description here
    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.



    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;
    }


    Here is a snippet from the JSON response from my url request






    {
    "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"
    }
    ]
    }
    ]
    }








    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?



    getData():



     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<String>() {
    @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 < 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);
    }


    }



    Logcat Error:



    enter image description here



    Other relevant code:



    ElectsRvAdapter: Recycler view adapter for the Elect class



    public class ElectsRvAdapter extends 
    RecyclerView.Adapter<ElectsRvAdapter.MyViewHolder> {

    private Context context;
    private List<Elects> electsList;

    public ElectsRvAdapter(){

    }

    public ElectsRvAdapter(Context context, List<Elects> 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);
    }
    }


    }



    SingleElection: Activity that displays more detailed information about the election



    public class SingleElection extends AppCompatActivity {

    private List<Elects> electsList;

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

    electsList = new ArrayList<>();

    //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);

    }


    }



    To sum up:




    1. How can I alter rmy getData() function to properly iterate through nested JSON arrays.

    2. How should I structure my Elects class to receive the JSON data in the easiest, most efficient way?


    Thanks Much! If you need any more code, let me know.










    share|improve this question



























      0












      0








      0








      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.
      enter image description here



      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.



      enter image description here
      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.



      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;
      }


      Here is a snippet from the JSON response from my url request






      {
      "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"
      }
      ]
      }
      ]
      }








      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?



      getData():



       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<String>() {
      @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 < 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);
      }


      }



      Logcat Error:



      enter image description here



      Other relevant code:



      ElectsRvAdapter: Recycler view adapter for the Elect class



      public class ElectsRvAdapter extends 
      RecyclerView.Adapter<ElectsRvAdapter.MyViewHolder> {

      private Context context;
      private List<Elects> electsList;

      public ElectsRvAdapter(){

      }

      public ElectsRvAdapter(Context context, List<Elects> 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);
      }
      }


      }



      SingleElection: Activity that displays more detailed information about the election



      public class SingleElection extends AppCompatActivity {

      private List<Elects> electsList;

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

      electsList = new ArrayList<>();

      //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);

      }


      }



      To sum up:




      1. How can I alter rmy getData() function to properly iterate through nested JSON arrays.

      2. How should I structure my Elects class to receive the JSON data in the easiest, most efficient way?


      Thanks Much! If you need any more code, let me know.










      share|improve this question
















      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.
      enter image description here



      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.



      enter image description here
      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.



      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;
      }


      Here is a snippet from the JSON response from my url request






      {
      "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"
      }
      ]
      }
      ]
      }








      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?



      getData():



       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<String>() {
      @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 < 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);
      }


      }



      Logcat Error:



      enter image description here



      Other relevant code:



      ElectsRvAdapter: Recycler view adapter for the Elect class



      public class ElectsRvAdapter extends 
      RecyclerView.Adapter<ElectsRvAdapter.MyViewHolder> {

      private Context context;
      private List<Elects> electsList;

      public ElectsRvAdapter(){

      }

      public ElectsRvAdapter(Context context, List<Elects> 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);
      }
      }


      }



      SingleElection: Activity that displays more detailed information about the election



      public class SingleElection extends AppCompatActivity {

      private List<Elects> electsList;

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

      electsList = new ArrayList<>();

      //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);

      }


      }



      To sum up:




      1. How can I alter rmy getData() function to properly iterate through nested JSON arrays.

      2. How should I structure my Elects class to receive the JSON data in the easiest, most efficient way?


      Thanks Much! If you need any more code, let me know.






      {
      "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"
      }
      ]
      }
      ]
      }








      {
      "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"
      }
      ]
      }
      ]
      }









      java arrays json android-recyclerview






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 3 at 7:34









      Markus Kauppinen

      2,2103825




      2,2103825










      asked Jan 3 at 6:58









      GabrielGabriel

      619




      619
























          1 Answer
          1






          active

          oldest

          votes


















          0














          First of all you are missing two closing parenthesis in the JSON you posted.



          Now parsing the given JSON,



          JSONObject jsonObject = new JSONObject(response);


          //Only one array needed for contests
          JSONArray contestsArray = jsonObject.getJSONArray("contests");
          for(int i=0;i<=contestsArray.length();i++)
          {
          JSONObject ContestObject=new JSONObject();

          //getting data of first contest object
          ContestObject=contestsArray.getJSONObject(i);

          String ContestType=ContestObject.getString("type");
          //Eg:- ContestType will have value "general" in the first iteration

          JSONObject DistrictObject=ContestObject.getJSONObject("district");
          //access data inside District Object using this object


          JSONArray candidates=ContestObject.getJSONArray("candidates");
          //loop through this array for all candidates data in the current contest Object

          //here parse data of each contest object
          }


          This is just the logic for parsing. You can create lists or add the data wherever you want from according to your needs. Hope it helps.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54017656%2fandroid-studio-parsing-multiple-nested-json-arrays%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            First of all you are missing two closing parenthesis in the JSON you posted.



            Now parsing the given JSON,



            JSONObject jsonObject = new JSONObject(response);


            //Only one array needed for contests
            JSONArray contestsArray = jsonObject.getJSONArray("contests");
            for(int i=0;i<=contestsArray.length();i++)
            {
            JSONObject ContestObject=new JSONObject();

            //getting data of first contest object
            ContestObject=contestsArray.getJSONObject(i);

            String ContestType=ContestObject.getString("type");
            //Eg:- ContestType will have value "general" in the first iteration

            JSONObject DistrictObject=ContestObject.getJSONObject("district");
            //access data inside District Object using this object


            JSONArray candidates=ContestObject.getJSONArray("candidates");
            //loop through this array for all candidates data in the current contest Object

            //here parse data of each contest object
            }


            This is just the logic for parsing. You can create lists or add the data wherever you want from according to your needs. Hope it helps.






            share|improve this answer




























              0














              First of all you are missing two closing parenthesis in the JSON you posted.



              Now parsing the given JSON,



              JSONObject jsonObject = new JSONObject(response);


              //Only one array needed for contests
              JSONArray contestsArray = jsonObject.getJSONArray("contests");
              for(int i=0;i<=contestsArray.length();i++)
              {
              JSONObject ContestObject=new JSONObject();

              //getting data of first contest object
              ContestObject=contestsArray.getJSONObject(i);

              String ContestType=ContestObject.getString("type");
              //Eg:- ContestType will have value "general" in the first iteration

              JSONObject DistrictObject=ContestObject.getJSONObject("district");
              //access data inside District Object using this object


              JSONArray candidates=ContestObject.getJSONArray("candidates");
              //loop through this array for all candidates data in the current contest Object

              //here parse data of each contest object
              }


              This is just the logic for parsing. You can create lists or add the data wherever you want from according to your needs. Hope it helps.






              share|improve this answer


























                0












                0








                0







                First of all you are missing two closing parenthesis in the JSON you posted.



                Now parsing the given JSON,



                JSONObject jsonObject = new JSONObject(response);


                //Only one array needed for contests
                JSONArray contestsArray = jsonObject.getJSONArray("contests");
                for(int i=0;i<=contestsArray.length();i++)
                {
                JSONObject ContestObject=new JSONObject();

                //getting data of first contest object
                ContestObject=contestsArray.getJSONObject(i);

                String ContestType=ContestObject.getString("type");
                //Eg:- ContestType will have value "general" in the first iteration

                JSONObject DistrictObject=ContestObject.getJSONObject("district");
                //access data inside District Object using this object


                JSONArray candidates=ContestObject.getJSONArray("candidates");
                //loop through this array for all candidates data in the current contest Object

                //here parse data of each contest object
                }


                This is just the logic for parsing. You can create lists or add the data wherever you want from according to your needs. Hope it helps.






                share|improve this answer













                First of all you are missing two closing parenthesis in the JSON you posted.



                Now parsing the given JSON,



                JSONObject jsonObject = new JSONObject(response);


                //Only one array needed for contests
                JSONArray contestsArray = jsonObject.getJSONArray("contests");
                for(int i=0;i<=contestsArray.length();i++)
                {
                JSONObject ContestObject=new JSONObject();

                //getting data of first contest object
                ContestObject=contestsArray.getJSONObject(i);

                String ContestType=ContestObject.getString("type");
                //Eg:- ContestType will have value "general" in the first iteration

                JSONObject DistrictObject=ContestObject.getJSONObject("district");
                //access data inside District Object using this object


                JSONArray candidates=ContestObject.getJSONArray("candidates");
                //loop through this array for all candidates data in the current contest Object

                //here parse data of each contest object
                }


                This is just the logic for parsing. You can create lists or add the data wherever you want from according to your needs. Hope it helps.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 7 at 12:58









                Nabil Mohammed NalakathNabil Mohammed Nalakath

                382416




                382416
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54017656%2fandroid-studio-parsing-multiple-nested-json-arrays%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas