You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Volley解析JSON报错:JSONArray无法转为JSONObject求助

解决Volley请求JSON时的类型转换异常问题

嘿,我来帮你搞定这个问题!你遇到的org.json.JSONException完全是因为API返回了两种不同格式的JSON响应,而你的代码只处理了其中一种情况:

问题根源

你用了JsonObjectRequest来发起请求,但这个请求类只能处理根节点是JSONObject的响应。当API直接返回JSON数组时,Volley会尝试把数组转换成JSONObject,这就触发了类型转换异常。

解决方案:用StringRequest兼容两种格式

我们可以先把响应以字符串形式获取,再手动判断它是JSON数组还是JSONObject,分别处理两种情况。这样就能同时兼容你提到的两种API返回格式了。

替换你原来的JsonObjectRequest代码,改成下面这样:

StringRequest request = new StringRequest(Request.Method.GET, url, 
    new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                // 用JSONTokener判断响应类型
                Object json = new JSONTokener(response).nextValue();
                mExampleList.clear(); // 先清空列表,避免重复添加

                if (json instanceof JSONArray) {
                    // 处理直接返回JSON数组的情况
                    JSONArray jsonArray = (JSONArray) json;
                    Log.d("1", "onResponse: 处理JSON数组格式");
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject hit = jsonArray.getJSONObject(i);
                        addArticleToList(hit);
                    }
                } else if (json instanceof JSONObject) {
                    // 处理包含articles对象的JSONObject情况
                    JSONObject responseObj = (JSONObject) json;
                    JSONObject articlesObj = responseObj.getJSONObject("articles");
                    Log.d("1", "onResponse: 处理articles对象格式");
                    // 遍历articles里的所有键值对
                    Iterator<String> keys = articlesObj.keys();
                    while (keys.hasNext()) {
                        String key = keys.next();
                        JSONObject hit = articlesObj.getJSONObject(key);
                        addArticleToList(hit);
                    }
                }

                // 更新适配器
                mExampleAdapter = new ExampleAdapter(MainActivity.this, mExampleList);
                mRecyclerView.setAdapter(mExampleAdapter);
                mExampleAdapter.notifyDataSetChanged(); // 确保数据刷新

            } catch (JSONException e) {
                e.printStackTrace();
                Log.d("1", "onResponse: 解析JSON出错");
            }
        }
    }, 
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("1", "onErrorResponse: Error response");
            error.printStackTrace();
        }
    });

mRequestQueue.add(request);

然后添加一个复用的方法来提取文章数据(避免重复代码):

private void addArticleToList(JSONObject hit) throws JSONException {
    // 注意:第二个JSON里有个拼写错误"locatoin",如果API实际返回是这个,要改成对应的key
    String title = hit.getString("title");
    String imageUrl = hit.getString("imageURL");
    String article = hit.getString("content");
    String author = hit.getString("author");
    String date = hit.getString("time");
    mExampleList.add(new ExampleItem(imageUrl, title, article, author, date));
    Log.d("1", "添加了一篇文章: " + title);
}

额外提醒

  • 注意你提供的第二个JSON里有个字段拼写错误:locatoin(正确应该是location),如果API实际返回就是这个错误拼写,提取的时候要对应上,否则会抛出字段找不到的异常。
  • 每次解析前清空列表mExampleList.clear(),避免多次请求时数据重复累积。

这样修改后,你的代码就能同时处理两种不同的JSON响应格式,不会再出现类型转换的异常啦!

内容的提问来源于stack exchange,提问作者adarsh keshri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:02:38