Android Studio请求PHP接口时json_decode()返回NULL问题排查
问题根因
- 两端表现不一致的核心原因是:Chrome发起请求时会自动完成参数URL编码、设置标准表单请求头,PHP可以正常解析参数;而原生
HttpURLConnection默认不会做这些处理,直接拼接JSON传参会破坏POST表单结构,导致PHP拿到的参数不是完整合法的JSON串,json_decode自然返回NULL - 现有Android代码存在3个明确问题:
- 直接拼接未编码的JSON字符串:JSON自带的
"、{}、:、空格、&等特殊字符会截断参数,导致$_POST['attrArr']拿到的是残缺内容 - 未设置POST表单对应的
Content-Type请求头,PHP无法按标准表单格式解析传入的请求体 - 提前调用
httpURLConnection.connect(),在连接建立后再配置请求参数不会生效
- 直接拼接未编码的JSON字符串:JSON自带的
修复方案
1. 核心修复:修改Android端请求逻辑
替换doInBackground方法内的代码,重点处理参数编码、请求头配置、连接逻辑:
@Override protected String doInBackground(String... params) { String attrArr = params[1]; String serverURL = params[0]; // 对JSON参数做URL编码,转义所有特殊字符,避免破坏表单结构 String postParameters = "attrArr=" + URLEncoder.encode(attrArr, "UTF-8"); try { URL url = new URL(serverURL); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setReadTimeout(5000); httpURLConnection.setConnectTimeout(5000); httpURLConnection.setRequestMethod("POST"); // 设置标准表单请求头,指定UTF-8编码 httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); httpURLConnection.setDoOutput(true); // 移除提前调用的connect(),获取输出流时会自动建立连接,所有配置都会生效 OutputStream outputStream = httpURLConnection.getOutputStream(); outputStream.write(postParameters.getBytes("UTF-8")); outputStream.flush(); outputStream.close(); int responseStatusCode = httpURLConnection.getResponseCode(); Log.d(TAG, "POST response code - " + responseStatusCode); InputStream inputStream; if(responseStatusCode == HttpURLConnection.HTTP_OK) { inputStream = httpURLConnection.getInputStream(); } else { inputStream = httpURLConnection.getErrorStream(); } InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); StringBuilder sb = new StringBuilder(); String line; while((line = bufferedReader.readLine()) != null){ sb.append(line); } bufferedReader.close(); return sb.toString(); } catch (Exception e) { Log.d(TAG, "InsertData: Error ", e); return "Error: " + e.getMessage(); } }
注意:PHP接收
$_POST参数时会自动对URL编码的内容做解码,拿到的是原始完整JSON串,不需要额外调用stripslashes()处理,反而可能破坏JSON结构。
2. PHP端加容错与调试逻辑
如果修改Android端后仍解析失败,先在PHP端增加JSON错误校验,快速定位问题:
<?php $attrArr = isset($_POST['attrArr']) ? trim($_POST['attrArr']) : ''; $data = json_decode($attrArr, true); // 校验JSON解析结果 if (json_last_error() !== JSON_ERROR_NONE) { echo "解析失败,错误原因:" . json_last_error_msg(); echo " 接收到的参数内容:" . $attrArr; exit; } // 后续业务逻辑 echo "gettype($data): " . gettype($data); ?>
常见解析失败场景:
- 参数被截断:未做URL编码时,JSON里如果包含
&字符,PHP会把它识别为参数分隔符,导致attrArr只拿到&之前的残缺内容 - 多余转义字符:仅当PHP版本低于5.4且开启了魔术引号时才需要用
stripslashes(),新版本PHP默认关闭该配置,强行调用会把合法JSON转成非法格式 - 首尾不可见字符:
trim()可以去掉参数首尾的BOM头、换行、空格等不可见字符,避免解析失败
验证步骤
- 重新运行Android端发起请求,正常情况下PHP端会返回
gettype($data): array - 如果仍报错,根据PHP返回的错误原因,对比接收到的参数内容和Android端
resultObject.toString()的输出是否完全一致,排查是否存在内容截断、多余字符问题
内容的提问来源于stack exchange,提问作者helpmeplz
相关产品推荐
相关产品推荐

