Android通过Volley请求PHP接口报错:String无法转为JSONObject求助
解决Android Volley无法将String转为JSONObject的问题
嘿,作为刚入门一个月的新手,碰到这个问题太正常了,我来帮你一步步排查解决:
首先排查PHP端的问题(这是最可能的根源)
你的PHP代码有几个容易踩的小坑,直接导致返回的内容不是合法的JSON格式:
编码设置拼写错误
你写的mysqli_query($connect,"SET NAME 'uft8'");里,NAME应该是NAMES,uft8是utf8的拼写错误,这会导致数据库返回的字符乱码,甚至直接破坏JSON结构。缺少错误处理,无数据/查询失败时返回非法JSON
如果数据库连接失败、查询语句出错,或者找不到对应ID的数据,$row会变成null,json_encode(null)会输出字符串"null"——这不是合法的JSONObject,Android端自然解析失败。未设置正确的响应头
服务器没明确告诉客户端返回的是JSON格式,Volley可能会把响应当成普通字符串处理,增加解析失败的概率。
修复后的PHP代码:
<?php // 开发阶段开启错误提示,上线后记得关闭 error_reporting(E_ALL); ini_set('display_errors', 1); // 明确设置响应为JSON格式 header('Content-Type: application/json; charset=utf-8'); $connect = mysqli_connect("localhost","root","","bkguardian"); // 检查数据库连接是否成功 if (!$connect) { echo json_encode(['error' => '数据库连接失败: ' . mysqli_connect_error()]); exit; } // 修正编码设置 mysqli_query($connect,"SET NAMES 'utf8'"); // 检查是否收到id参数 if (!isset($_POST['id'])) { echo json_encode(['error' => '缺少必要的id参数']); exit; } $id = $_POST['id']; // 用预处理语句防止SQL注入!新手一定要养成这个安全习惯 $query = "SELECT * FROM user_lock_information WHERE id = ? LIMIT 1"; $stmt = mysqli_prepare($connect, $query); mysqli_stmt_bind_param($stmt, "s", $id); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); $row = mysqli_fetch_assoc($result); if ($row) { // 找到数据,返回用户信息JSON echo json_encode($row); } else { // 无匹配数据时,返回合法的JSON对象(避免返回null字符串) echo json_encode(['status' => 'no_data', 'message' => '未找到对应ID的用户信息']); } // 关闭资源 mysqli_stmt_close($stmt); mysqli_close($connect); ?>
然后调整Android端代码
你的JsonObjectRequest遇到非JSON内容时会直接报错,建议做两个优化:
- 先用StringRequest排查返回内容
在正式解析JSON前,先换成StringRequest打印返回内容,快速定位问题:
private void getUserLockInformation(String url, final String id) { RequestQueue requestQueue = Volley.newRequestQueue(LogInActivity.this); StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // 打印返回内容,确认是否为合法JSON Log.d("VolleyResponse", "服务器返回: " + response); try { JSONObject jsonObject = new JSONObject(response); // 处理无数据的情况 if (jsonObject.has("status") && jsonObject.getString("status").equals("no_data")) { Toast.makeText(LogInActivity.this, jsonObject.getString("message"), Toast.LENGTH_SHORT).show(); return; } // 正常解析用户锁信息 Integer numColumn = jsonObject.length(); lockData = new Integer[numColumn -1]; String nameHandle; for (int i = 0; i <= numColumn-1; i++){ nameHandle ="lock".concat(String.valueOf(i+1)); lockData[i] = jsonObject.getInt(nameHandle); } } catch (JSONException e) { e.printStackTrace(); Toast.makeText(LogInActivity.this, "解析JSON失败: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(LogInActivity.this, "系统错误,请联系管理员!",Toast.LENGTH_LONG).show(); Log.d("AAA","错误详情: \n" +error.toString()); } }){ @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String,String> param = new HashMap<>(); param.put("id",id); return param; } }; requestQueue.add(stringRequest); }
- 新增无数据判断逻辑
当PHP返回无数据的JSON时,提前捕获状态,避免直接去取lockX字段导致异常。
最后测试步骤
- 用Postman或类似工具模拟POST请求,传入id参数,确认服务器返回的是合法JSON。
- 运行修复后的代码,查看Log里的返回内容,确认无误后再正常使用。
这样一步步下来,应该就能解决你遇到的String cannot be converted to JSONObject错误啦!
内容的提问来源于stack exchange,提问作者AnhVu Bkp
相关产品推荐
相关产品推荐

