Wentao Yang
Wentao Yang

Reputation: 35

Value type org.json.JSONObject cannot be converted to JSONArray

Not sure where I make a mistake.

Code:

public class VaccinationTotalUSA extends Fragment {

RecyclerView rvRecentRecord;
ProgressBar progressBar;

private static final String TAG = VaccinationTotalUSA.class.getSimpleName();

ArrayList<VaccinationTimeline> recentRecords;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_vaccination, container, false);


    // call view
    rvRecentRecord = view.findViewById(R.id.vaccinationRecord);
    progressBar = view.findViewById(R.id.progress_circular_vaccination);
    rvRecentRecord.setLayoutManager(new LinearLayoutManager(getActivity()));

    // Volley Fetch
    getDataFromServer();

    return view;
}

private void showRecyclerView() {
    VaccinationAdapter vaccinationAdapter = new VaccinationAdapter(recentRecords);
    rvRecentRecord.setAdapter(vaccinationAdapter);
}

private void getDataFromServer() {
    String url = "https://disease.sh/v3/covid-19/vaccine/coverage/countries/USA";

    recentRecords = new ArrayList<>();

    StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {

            progressBar.setVisibility(View.GONE);

            if (response != null) {
                Log.e(TAG, "onResponse:" + response);
                try {

                    JSONObject jsonObject = new JSONObject(response);
                    JSONArray jsonArray = jsonObject.getJSONArray("timeline");

                    for (int i = 0; i < jsonArray.length(); i++) {

                        JSONObject data = jsonArray.getJSONObject(i);

                        Iterator key = data.keys();
                        while (key.hasNext()) {
                            String timedata = key.next().toString();
                            recentRecords.add(new VaccinationTimeline(key, timedata));
                        }

                    }

                    showRecyclerView();
                }catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    progressBar.setVisibility(View.GONE);
                    Log.e(TAG, "onResponse" + error);
                }
            });
    Volley.newRequestQueue(getActivity()).add(stringRequest);
}

}

JSON: Note: Can't really use jsonObject.getString() on timeline nested list since everything gets updated each day, i.e, 4/18/2021 data comes in, 3/19/2021 will be removed

{
"country": "USA",
"timeline": {
    "3/19/21": 118313818,
    "3/20/21": 121441497,
    "3/21/21": 124481412,
    "3/22/21": 126509736,
    "3/23/21": 128217029,
    "3/24/21": 130473853,
    "3/25/21": 133305295,
    "3/26/21": 136684688,
    "3/27/21": 140180735,
    "3/28/21": 143462691,
    "3/29/21": 145812835,
    "3/30/21": 147602345,
    "3/31/21": 150273292,
    "4/1/21": 153631404,
    "4/2/21": 157606463,
    "4/3/21": 161688422,
    "4/4/21": 165053746,
    "4/5/21": 167187795,
    "4/6/21": 168592075,
    "4/7/21": 171476655,
    "4/8/21": 174879716,
    "4/9/21": 178837781,
    "4/10/21": 183467709,
    "4/11/21": 187047131,
    "4/12/21": 189692045,
    "4/13/21": 192282781,
    "4/14/21": 194791836,
    "4/15/21": 198317040,
    "4/16/21": 202282923,
    "4/17/21": 202282923
}

}

I have tried many ways to display this json data, with and without iterator. I want to use iterator because I want to be able to retrieve both list name and data inside of list, i.e, 4/17/2021:1111111 Error Output:

E/VaccinationTotalUSA: onResponse:{"country":"USA","timeline":{"3/19/21":118313818,"3/20/21":121441497,"3/21/21":124481412,"3/22/21":126509736,"3/23/21":128217029,"3/24/21":130473853,"3/25/21":133305295,"3/26/21":136684688,"3/27/21":140180735,"3/28/21":143462691,"3/29/21":145812835,"3/30/21":147602345,"3/31/21":150273292,"4/1/21":153631404,"4/2/21":157606463,"4/3/21":161688422,"4/4/21":165053746,"4/5/21":167187795,"4/6/21":168592075,"4/7/21":171476655,"4/8/21":174879716,"4/9/21":178837781,"4/10/21":183467709,"4/11/21":187047131,"4/12/21":189692045,"4/13/21":192282781,"4/14/21":194791836,"4/15/21":198317040,"4/16/21":202282923,"4/17/21":202282923}}
W/System.err: org.json.JSONException: Value {"country":"USA","timeline":{"3\/19\/21":118313818,"3\/20\/21":121441497,"3\/21\/21":124481412,"3\/22\/21":126509736,"3\/23\/21":128217029,"3\/24\/21":130473853,"3\/25\/21":133305295,"3\/26\/21":136684688,"3\/27\/21":140180735,"3\/28\/21":143462691,"3\/29\/21":145812835,"3\/30\/21":147602345,"3\/31\/21":150273292,"4\/1\/21":153631404,"4\/2\/21":157606463,"4\/3\/21":161688422,"4\/4\/21":165053746,"4\/5\/21":167187795,"4\/6\/21":168592075,"4\/7\/21":171476655,"4\/8\/21":174879716,"4\/9\/21":178837781,"4\/10\/21":183467709,"4\/11\/21":187047131,"4\/12\/21":189692045,"4\/13\/21":192282781,"4\/14\/21":194791836,"4\/15\/21":198317040,"4\/16\/21":202282923,"4\/17\/21":202282923}} of type org.json.JSONObject cannot be converted to JSONArray
        at org.json.JSON.typeMismatch(JSON.java:112)
        at org.json.JSONArray.<init>(JSONArray.java:96)
        at org.json.JSONArray.<init>(JSONArray.java:108)
        at com.programming_concept.senior_project.VaccinationTotalUSA$1.onResponse(VaccinationTotalUSA.java:83)
W/System.err:     at com.programming_concept.senior_project.VaccinationTotalUSA$1.onResponse(VaccinationTotalUSA.java:69)
        at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:82)
        at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:29)
        at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Upvotes: 1

Views: 2306

Answers (3)

Sammy T
Sammy T

Reputation: 1924

You're trying to set the "timeline" value to a JSONArray variable while that value would actually be a JSONObject. Here's a way you can retrieve both the key and value:

JSONObject jsonObject = new JSONObject(response);
JSONObject subObject = jsonObject.getJSONObject("timeline");

// Separate the keys into a JSONArray
JSONArray keys = subObject.names();

// Retrieve the keys and values
for(int i=0; i < keys.length(); i++) {
    String key = keys.getString(i);
    int value = subObject.getInt(key);
            
    Log.d("LOG_TAG", key + " : " + value);
}

Upvotes: 0

Deepak Jain
Deepak Jain

Reputation: 347

You can try the follwing code. I have hardcoded the json response in the Main class itself. Also I have used ObjectMapper which is much better than using JsonObject class

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;


public class AssessmentBridgeApplication {

    public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
        String json = "{\"country\":\"USA\",\"timeline\":{\"3/19/21\":118313818,\"3/20/21\":121441497,\"3/21/21\":124481412,\"3/22/21\":126509736,\"3/23/21\":128217029,\"3/24/21\":130473853,\"3/25/21\":133305295,\"3/26/21\":136684688,\"3/27/21\":140180735,\"3/28/21\":143462691,\"3/29/21\":145812835,\"3/30/21\":147602345,\"3/31/21\":150273292,\"4/1/21\":153631404,\"4/2/21\":157606463,\"4/3/21\":161688422,\"4/4/21\":165053746,\"4/5/21\":167187795,\"4/6/21\":168592075,\"4/7/21\":171476655,\"4/8/21\":174879716,\"4/9/21\":178837781,\"4/10/21\":183467709,\"4/11/21\":187047131,\"4/12/21\":189692045,\"4/13/21\":192282781,\"4/14/21\":194791836,\"4/15/21\":198317040,\"4/16/21\":202282923,\"4/17/21\":202282923}}";
        ObjectMapper mapper = new ObjectMapper();
        VaccinationRecords vaccinationRecords  = new VaccinationRecords();
        vaccinationRecords = mapper.readValue(json, VaccinationRecords.class);
        System.out.println(vaccinationRecords.getTimeline());
    }
}

=========================

import java.util.Map;

public class VaccinationRecords {

private String country;

Map<String, Object> timeline;

public String getCountry() {
    return country;
}

public void setCountry(String country) {
    this.country = country;
}

public Map<String, Object> getTimeline() {
    return timeline;
}

public void setTimeline(Map<String, Object> timeline) {
    this.timeline = timeline;
}

}

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1006614

There is no array in that JSON. In JSON, an array is denoted by square brackets ([ and ]). There are no square brackets in that JSON.

You have an outer JSON object, with two properties: country and timeline. timeline is another JSON object, with keys based on dates and values that are integers.

So, you need to revise your plans to work with the JSON as it is, which means JSONArray jsonArray = jsonObject.getJSONArray("timeline"); needs to turn into JSONObject timelineJson = jsonObject.getJSONObject("timeline");.

And note that there are many better JSON parsers available for Android, such as Moshi.

Upvotes: 1

Related Questions