值类型 org.json.JSONObject 无法转换为 JSONArray

Posted

技术标签:

【中文标题】值类型 org.json.JSONObject 无法转换为 JSONArray【英文标题】:Value type org.json.JSONObject cannot be converted to JSONArray 【发布时间】:2021-07-12 13:47:56 【问题描述】:

不知道我在哪里犯了错误。

代码:

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:注意: 不能真正在时间线嵌套列表上使用 jsonObject.getString(),因为每天都会更新所有内容,即 2021 年 4 月 18 日的数据进来,3 /19/2021 将被删除


"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

我尝试了很多方法来显示这个 json 数据,有和没有迭代器。我想使用迭代器,因为我希望能够在列表中检索列表名称和数据,即 4/17/2021:1111111 错误输出:

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)

【问题讨论】:

您可以考虑使用 Retrofit2,我在一个加载疫苗数据的应用程序中也使用过。您可以使用 GSONConverter 工厂对其进行私有化,以将您的数据解析为 java 对象。像魅力一样工作 【参考方案1】:

该 JSON 中没有数组。在 JSON 中,数组用方括号表示([])。该 JSON 中没有方括号。

您有一个外部 JSON 对象,具有两个属性:countrytimelinetimeline 是另一个 JSON 对象,其键基于日期和整数值。

因此,您需要修改计划以按原样使用 JSON,这意味着 JSONArray jsonArray = jsonObject.getJSONArray("timeline"); 需要转换为 JSONObject timelineJson = jsonObject.getJSONObject("timeline");

请注意,有许多更好的适用于 Android 的 JSON 解析器,例如 Moshi。

【讨论】:

【参考方案2】:

您正在尝试将“时间线”值设置为JSONArray 变量,而该值实际上是JSONObject。这是一种可以同时检索键和值的方法:

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

【讨论】:

org.json.JSONObject 无法转换为 JSONArray 问题已解决。但仍然收到错误消息(E/VaccinationTotalUSA: onResponse:"country":"USA","timeline":"3/19/21":118313818,"3/20/21":121441497,"3/21 /21":124481412, ... 4/14/21":194791836,"4/15/21":198317040,"4/16/21":202282923,"4/17/21":202282923) . 知道什么可能导致这个问题吗?因为有键和值,我需要将数组更改为 Map 吗? 它显示为错误,因为您使用Log.e() 在您的onResponse() 中打印了该消息。你有Log.e(TAG, "onResponse:" + response); 当我认为你打算放Log.d(TAG, "onResponse:" + response); 我注意到了,忘记删除我以前的 cmets。感谢您的答复。现在,我遇到了“未连接适配器,跳过布局”的问题。如果你熟悉,可以看看这个链接:***.com/questions/67149764/…。【参考方案3】:

您可以尝试以下代码。我在 Main 类本身中硬编码了 json 响应。我也使用过 ObjectMapper,它比使用 JsonObject 类好得多

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;

【讨论】:

以上是关于值类型 org.json.JSONObject 无法转换为 JSONArray的主要内容,如果未能解决你的问题,请参考以下文章

org.json.JSONObject & org.json.JSONArray

如何使用 ResponseEntity 返回 JSONObject 而不是 HashMap? (未找到类型返回值的转换器:类 org.json.JSONObject)

org.json.JSONObject$1 类型的值 null 无法转换为 JSONObject

未找到 Java 类型、类 org.json.JSONObject.... 和 MIME 媒体类型、application/json 的消息正文阅读器

JSONObject类参数问题

net.sf.json.JSONObject 和org.json.JSONObject 的差别