json_error_utf8 根本原因是字符串含非法utf-8字节序列,常见于gbk编码响应、bom头、数据库编码不一致、不可见控制字符或中间层污染;可用bin2hex、mb_check_encoding快速诊断,修复用mb_convert_encoding自动转码+json_invalid_utf8_ignore容错。

哪些情况会触发 JSON_ERROR_UTF8?
常见真实场景包括:
- 接口返回的是 GBK/GB2312 编码,比如老系统、某些国内 HTTP 接口直接输出中文但没声明 charset,PHP 拿到的是乱码字节,强行当 UTF-8 解析就崩
-
字符串开头带 BOM 头(
EF BB BF),尤其 Windows 记事本保存的 UTF-8 文件,前面三个隐藏字节会让 json_decode 直接报 UTF8 错误 - 从数据库或文件读取时编码不一致,比如 MySQL 连接用的是 latin1,但字段存了中文,查出来就是乱码字节
-
用户粘贴/剪贴板带不可见控制字符(如零宽空格、U+200B、U+FEFF 等),肉眼看不见,
bin2hex()一查就露馅 - curl 或 file_get_contents 获取响应时被中间层污染,比如代理注入 HTML、调试信息、Token 水印(如知识库中反复出现的“用码道免费领 1 个月 Token”)
怎么快速确认是不是 UTF-8 问题?
别猜,直接看原始字节:
- 用
bin2hex(substr($str, 0, 10))查前 10 字节,如果开头是efbbbf就是 BOM - 用
mb_check_encoding($str, 'UTF-8')返回false,基本可断定编码异常 - 用
json_last_error_msg()输出错误信息,明确看到 “Malformed UTF-8 characters” 就是它
安全可靠的修复写法(一行生效)
不依赖版本、不改源数据,直接清理再解码:
$clean = mb_convert_encoding($raw, 'UTF-8', 'UTF-8, GBK, GB2312, BIG5');
$data = json_decode($clean, true);
if ($data === null && json_last_error() === JSON_ERROR_UTF8) {
// 仍失败?启用容错模式(PHP 7.2+)
$clean = mb_convert_encoding($raw, 'UTF-8', 'auto');
$data = json_decode($clean, true, 512, JSON_INVALID_UTF8_IGNORE);
}
说明:
• mb_convert_encoding(..., 'UTF-8', 'UTF-8, GBK, ...') 表示“优先按 UTF-8 解,不行就试 GBK,再不行试 GB2312”,自动兜底
• JSON_INVALID_UTF8_IGNORE 会跳过非法字节,不中断解析(适合日志、非关键字段)
预防比修复更重要
日常开发中建议加一层“输入守门员”:
- 调用
curl_exec()后立刻trim()+mb_convert_encoding(),别等json_decode报错才处理 - 第三方 API 文档写明 GBK?那就固定加
mb_convert_encoding($res, 'UTF-8', 'GBK') - 数据库连接统一设
SET NAMES utf8mb4,字段也用utf8mb4_unicode_ci - 写入 JSON 前用
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)主动暴露问题
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











