简体   繁体   中英

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, ie, 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, ie, 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)

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 .

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

}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM