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

Android Volley提交RecyclerView文本参数时JSON转换错误求助

问题排查与解决方案

嘿,我来帮你搞定这个问题!首先咱们先拆解一下你遇到的错误:

"Value no of type java.lang.String cannot be converted to JSONObject"

这个错误的核心原因是:服务器返回的响应不是你预期的JSON格式,而是字符串"no",当你尝试用new JSONObject(response)去解析这个字符串时,自然就会抛出转换异常。

为什么会返回"no"?

看你loadDistricts()方法里的代码:你用了Request.Method.GET请求,但同时重写了getParams()方法。这里有个Volley的关键知识点:GET请求不会自动把getParams()里的参数添加到请求中——GET请求的参数需要手动拼在URL末尾,而getParams()是给POST请求准备的,用来传递请求体参数。

这就导致你的服务器根本没收到state参数,所以返回了"no"(应该是服务器找不到对应数据时的默认返回)。

解决方案

方案1:改用POST请求(推荐)

把请求方法改成Request.Method.POST,这样Volley会自动把getParams()里的参数作为请求体发送给服务器,服务器就能正确获取到state参数了:

private void loadDistricts() { 
    RequestQueue queue = Volley.newRequestQueue(States.this); 
    // 把GET请求改为POST请求
    StringRequest request = new StringRequest(Request.Method.POST, url_districts, 
        new Response.Listener<String>() { 
            @Override 
            public void onResponse(String response) { 
                // 先打印响应内容,方便排查问题
                Log.d("DistrictResponse", response);
                try { 
                    JSONObject obj = new JSONObject(response); 
                    JSONArray statesArray = obj.getJSONArray("districts"); 
                    for(int i=0; i<statesArray.length(); i++) { 
                        JSONObject stateObject = statesArray.getJSONObject(i); 
                        String DtHindi = stateObject.getString("DtHindi"); 
                        String DTName = stateObject.getString("DTName"); 
                        String District11 = stateObject.getString("District11"); 
                        District districts = new District(DtHindi, DTName, District11); 
                        dist_list.add(districts); 
                        districtAdapter.notifyDataSetChanged(); 
                    } 
                } catch (JSONException e) { 
                    e.printStackTrace(); 
                    Toast.makeText(States.this, e.getMessage(), Toast.LENGTH_LONG).show(); 
                } 
            } 
        }, new Response.ErrorListener() { 
            @Override 
            public void onErrorResponse(VolleyError error) { 
                Toast.makeText(States.this, error.getMessage(), Toast.LENGTH_LONG).show(); 
            } 
        }){ 
            @Override 
            protected Map<String, String> getParams() throws AuthFailureError { 
                Map<String, String> map = new HashMap<String, String>(); 
                map.put("state", state.getText().toString()); 
                return map; 
            } 
        }; 
    queue.add(request); 
}

方案2:如果一定要用GET请求,手动拼接URL参数

把state参数直接拼在url_districts后面,注意要对参数值进行URL编码,避免特殊字符导致的问题:

private void loadDistricts() { 
    RequestQueue queue = Volley.newRequestQueue(States.this); 
    try {
        // 手动拼接参数到URL,并编码特殊字符
        String encodedState = URLEncoder.encode(state.getText().toString(), "UTF-8");
        String urlWithParams = url_districts + "?state=" + encodedState;
        
        StringRequest request = new StringRequest(Request.Method.GET, urlWithParams, 
            new Response.Listener<String>() { 
                @Override 
                public void onResponse(String response) { 
                    Log.d("DistrictResponse", response);
                    try { 
                        JSONObject obj = new JSONObject(response); 
                        JSONArray statesArray = obj.getJSONArray("districts"); 
                        for(int i=0; i<statesArray.length(); i++) { 
                            JSONObject stateObject = statesArray.getJSONObject(i); 
                            String DtHindi = stateObject.getString("DtHindi"); 
                            String DTName = stateObject.getString("DTName"); 
                            String District11 = stateObject.getString("District11"); 
                            District districts = new District(DtHindi, DTName, District11); 
                            dist_list.add(districts); 
                            districtAdapter.notifyDataSetChanged(); 
                        } 
                    } catch (JSONException e) { 
                        e.printStackTrace(); 
                        Toast.makeText(States.this, e.getMessage(), Toast.LENGTH_LONG).show(); 
                    } 
                } 
            }, new Response.ErrorListener() { 
                @Override 
                public void onErrorResponse(VolleyError error) { 
                    Toast.makeText(States.this, error.getMessage(), Toast.LENGTH_LONG).show(); 
                } 
            }); 
        queue.add(request); 
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        Toast.makeText(States.this, "参数编码失败", Toast.LENGTH_SHORT).show();
    }
}

额外需要修正的小问题

在state_recycler_view的长按事件里,你错误地调用了district_recycler_view.findViewHolderForAdapterPosition(position),这会导致空指针异常(因为此时district_recycler_view可能不可见或者没有对应位置的ViewHolder)。如果是要处理州的长按操作,应该改成针对state_recycler_view的逻辑:

@Override
public void onLongClick(View view, int position) {
    // 获取选中的州数据
    State selectedState = state_list.get(position);
    // 根据需求调整后续操作,比如填充到district输入框?
    // district.setText(selectedState.getSTName());
    dist_list.clear();
    district_recycler_view.setVisibility(View.GONE);
}

排查小技巧

在onResponse方法里先打印服务器返回的response内容,这样你就能清楚看到服务器到底返回了什么,方便快速定位问题:

@Override
public void onResponse(String response) {
    Log.d("ServerResponse", "返回内容:" + response);
    // 再进行后续解析逻辑
}

内容的提问来源于stack exchange,提问作者Vincent Rabha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:16