核心是确保整条链路统一utf-8编码并正确使用json_encode($data, json_unescaped_unicode),配合mb_convert_encoding转码、header('content-type: application/json; charset=utf-8')响应头及json_last_error_msg()排错。

PHP 8(包括 8.3 和 8.5)处理 JSON 中文乱码,核心不是“修 bug”,而是确保整条链路统一用 UTF-8 编码,并正确使用 json_encode() 的关键参数。乱码几乎从不来自函数本身,而是数据在某处被误读或误写。
确保输入字符串是合法 UTF-8
json_encode 只接受 UTF-8 字符串。如果源数据来自数据库、文件、POST 或旧系统,它可能实际是 GBK、ISO-8859-1 或带 BOM 的 UTF-8 —— 这些都会导致编码失败或静默转义。
- 先检测真实编码:
mb_detect_encoding($str, ['UTF-8', 'GBK', 'BIG5', 'ISO-8859-1'], true) - 确认是 GBK?用
mb_convert_encoding($str, 'UTF-8', 'GBK')转换 - 怀疑有 BOM?用
ltrim($str, "\xEF\xBB\xBF")清除 - 不确定又想兜底?
mb_convert_encoding($str, 'UTF-8', 'auto')(注意:'auto' 不可靠,仅作辅助)
必须加 JSON_UNESCAPED_UNICODE
默认情况下,json_encode 会把中文转成 \u4f60\u597d 形式。这不是乱码,是兼容性设计;但对人眼和调试不友好。加这个标志才能输出可读中文。
- 正确写法:
json_encode($data, JSON_UNESCAPED_UNICODE) - 推荐组合:
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT - PHP 5.4+ 支持,PHP 8 全系可用,无兼容问题
设置正确的 HTTP 响应头
即使 JSON 内容完全正确,浏览器也可能因响应头缺失而按错误编码解析,尤其在旧 WebView 或部分 IE 模式下。
- 必须在任何输出前调用:
header('Content-Type: application/json; charset=utf-8') - 检查 PHP 文件开头有没有 BOM 或空行(VS Code / Notepad++ 可查“编码”)
- 用
ob_start()开启缓冲,避免意外输出破坏 header - 框架用户(如 Laravel)通常自动处理,手动 echo 时务必自己加
验证并捕获失败情况
json_encode 返回 null 是明确的错误信号,不是随机现象。别只判空,要查原因。
- 编码失败后立刻查:
json_last_error_msg() - 常见错误:
JSON_ERROR_UTF8(含非法字节)、JSON_ERROR_SYNTAX(前端拼错或返回了 HTML)、JSON_ERROR_DEPTH(嵌套太深) - 解码时建议启用异常:
json_decode($json, true, 512, JSON_THROW_ON_ERROR) - 对不可序列化值(resource、Closure、循环引用)提前过滤,避免静默失败
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











