PHP返回JSON给Java需确保严格UTF-8无BOM、无额外输出,设置header('Content-Type: application/json; charset=utf-8'),用json_encode($data, JSON_UNESCAPED_UNICODE)并清理输出缓冲,Java端用InputStreamReader指定UTF-8读取。

PHP 返回 JSON 给 Java,关键不是“能不能”,而是“怎么确保 Java 能原样解析不报错”。核心在于 PHP 端输出必须是严格合法的 UTF-8 编码 JSON 字符串,且不能带任何额外输出(包括 BOM、空格、警告、Notice)。
PHP 输出 JSON 前必须清理输出缓冲并设置正确 header
Java 的 HttpURLConnection 或 OkHttp 默认对响应体敏感,哪怕开头多一个空格或 BOM,JSONObject 或 Gson 就会抛 JSONException: End of input at character 0 或类似解析失败错误。
- 调用
ob_clean()+ob_end_clean()清掉之前可能存在的输出缓存 - 必须显式设置:
header('Content-Type: application/json; charset=utf-8') - 避免在
json_encode()前后有echo、var_dump、print_r,哪怕被注释了也有可能触发输出(比如开启display_errors时 Notice 会输出) - 检查 PHP 文件本身是否为 UTF-8 无 BOM 格式(尤其 Windows 下用记事本保存极易带 BOM)
PHP json_encode() 的参数要慎选,特别是中文和 null 处理
Java 端通常期望标准 JSON:中文不转义、null 映射为 JSON null、数字不加引号。但默认 json_encode($data) 在某些 PHP 版本或配置下可能不符合。
- 强制 UTF-8 输出:用
JSON_UNESCAPED_UNICODE,否则中文变成\uXXXX,Java 虽能解析但可读性差、调试困难 - 处理
null值:PHP 的null经json_encode()后就是 JSONnull,无需额外操作;但注意不要用字符串"null"替代 - 避免浮点数精度问题:如果 PHP 中有
floatval(1.23),JSON 里会是1.2300000000000002,Java 解析后可能偏差;必要时用round($val, 2)或转成字符串再编码 - 示例安全写法:
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
Java 接收时别直接 new String(bytes),要用 response.getInputStream() + 指定编码
很多 Java 开发者用 connection.getInputStream() 读完字节数组,再用 new String(byte[], "UTF-8") 构造字符串——这看似合理,但若服务端 header 未明确声明 charset,部分 HTTP 客户端(如旧版 OkHttp)可能按 ISO-8859-1 解码,导致中文变乱码,进而 JSON 解析失败。
立即学习“PHP免费学习笔记(深入)”;
- 推荐方式:用
InputStreamReader显式指定 UTF-8:new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8) - 或者用 OkHttp 时,直接调用
response.body().string()(它会自动读取 Content-Type 中的 charset) - 如果手动拼接字符串,务必确认整个响应体字节流完整、无截断(检查
Content-Length或用readFully) - 收到字符串后,先用
Log.d("JSON", jsonStr)打印原始字符串,确认中文显示正常,再交给JSONObject或Gson.fromJson()
调试时最该看的三个地方:HTTP 状态码、响应头、原始响应体
别急着改 Java 解析逻辑。90% 的“JSON 解析失败”其实根本没到解析那步——是网络层或服务端就出错了。
- 先确认 HTTP 状态码是
200,不是500(PHP 报错但没关display_errors,HTML 错误页混在 JSON 里) - 用 Postman 或 curl 看响应头:
Content-Type是否含charset=utf-8,Content-Length是否合理 - 用 curl -v 或 Charles/Fiddler 抓包,看**原始响应体**:开头有没有空白?结尾有没有 PHP 关闭标签
?>后的换行?JSON 是否被 HTML 包裹? - PHP 端临时加日志:
file_put_contents('/tmp/debug.json', json_encode($data, JSON_UNESCAPED_UNICODE));,对比文件内容和实际响应是否一致
真正卡住的地方往往不在 JSON 格式本身,而在字符编码、输出控制、HTTP 协议细节这些“看不见”的环节。每次改完 PHP,务必用 curl 直接请求接口,把返回结果重定向到文件里用 hexdump 看前几个字节——BOM 就藏在那里。











