调接口时遇到过一次:页面白屏,日志里只有一行 json_encode 返回 false,连错误都没有。顺着数据往上查,发现是数据库里混进了一条 GBK 编码的旧记录。
先让错误说出来
json_encode 失败时不会主动抛异常,只会返回 false。紧接着调用 json_last_error_msg(),一般能看到「Malformed UTF-8 characters」或者「Type is not supported」。这两个提示基本能把范围缩小一半。
最常见的三类脏数据
- 字符串不是 UTF-8。比如从旧库导出的 GBK 内容,或者用户提交时编码被截断。
- 数组里混进了资源类型,比如 fopen 返回的句柄、mysqli 连接对象。
- 数值里出现了 NAN 或 INF,JSON 不支持这两种值。
临时排查可以在编码前先跑一遍 array_walk_recursive,把非 UTF-8 的字符串用 mb_convert_encoding 转一下,资源类型直接剔除。生产环境不要长期靠转换兜底,源头该改就改。
中文和斜杠的显示问题
内容没错但中文全变成 u4e2d u6587 这样的转义序列,这不是失败,是默认转义。加 JSON_UNESCAPED_UNICODE 就能原样输出中文。URL 里的斜杠被转成 /,加 JSON_UNESCAPED_SLASHES 即可。两个常量可以一起用,用竖线连接。
输出前留一层判断
不要直接 echo json_encode($data)。先赋值给变量,判断是不是 false,是就记日志并返回一个固定的错误结构。这样前端至少能拿到可解析的 JSON,而不是半截空响应。
说到底,json_encode 只是个翻译,数据本身干净比什么参数都重要。旧系统迁移时,先把字符集统一成 UTF-8,后面能少掉一大半这类问题。