json_decode() 解析失败默认静默返回 null,须用 json_last_error() 检查错误码;常见原因包括语法错误、utf-8 编码损坏、嵌套过深、内存不足及输入非标准 json 字符串。

json_decode() 返回 null 却没报错
这是最常被忽略的问题:PHP 的 json_decode() 在解析失败时默认静默返回 null,不抛异常、不打日志,容易误判为“数据为空”而非“解码失败”。
- 必须立刻用
json_last_error()检查错误码,不能只靠=== null判断 - 常见错误码:
JSON_ERROR_SYNTAX(非法 JSON)、JSON_ERROR_UTF8(UTF-8 编码损坏,比如 GBK 混入) - 如果输入是用户提交的 POST body 或文件内容,先用
trim()去首尾空白——BOM 头或换行符会导致JSON_ERROR_SYNTAX - 示例:
$json = file_get_contents('data.json');<br>$data = json_decode($json, true);<br>if ($data === null && json_last_error() !== JSON_ERROR_NONE) {<br> throw new RuntimeException('JSON 解码失败: ' . json_last_error_msg());<br>}
中文乱码或 JSON_ERROR_UTF8 错误
PHP 要求输入字符串必须是合法 UTF-8。很多接口或数据库导出的数据实际是 GBK/GB2312,直接传给 json_decode() 就会触发 JSON_ERROR_UTF8。
- 别用
iconv('GBK', 'UTF-8//IGNORE', $str)——//IGNORE会丢字,且 PHP 8+ 已弃用该写法 - 推荐用
mb_convert_encoding($str, 'UTF-8', 'auto'),它能自动识别 GBK/GB2312/UTF-8 等编码 - 若确定来源是 GBK,且环境支持,可用
mb_convert_encoding($str, 'UTF-8', 'GBK') - 注意:MySQL 查询结果若字段是
gbk_chinese_ci,需在 PDO 连接时设charset=gbk,或查询后统一转码
嵌套过深或超大 JSON 导致内存/深度限制报错
PHP 默认限制 JSON 解析深度为 512 层,且受 memory_limit 影响。遇到深层嵌套对象或几百 MB 的 JSON 文件,json_decode() 可能返回 null,但 json_last_error() 是 JSON_ERROR_DEPTH 或 JSON_ERROR_STATE_MISMATCH(常因内存不足中断解析)。
- 调大深度:PHP 7.3+ 支持第三个参数
$depth,如json_decode($json, true, 2048) - 超大 JSON 不要一次性
file_get_contents()加载——改用流式解析库(如jsonstream),或分块读取 + 正则切分(仅限结构简单场景) - 确认
memory_limit足够:一个 100MB 的 JSON 解析后数组可能占 300MB+ 内存 - 用
json_last_error_msg()查具体原因,别只看null
布尔值、null、数字被当成字符串传入
前端 JS 有时把 true、false、null 当作字符串发过来,比如 "true"、"null",后端没校验就直接 json_decode(),结果得到字符串而非对应类型。
立即学习“PHP免费学习笔记(深入)”;
- 典型现象:
json_decode('"true"', true)返回"true"(字符串),不是布尔true - 这不是
json_decode()的问题,而是输入本身不符合 JSON 规范——合法 JSON 的布尔字面量不带引号 - 解决方案:前端修复;或后端加预处理,用正则替换
"true"→true(慎用,易误伤) - 更安全的做法:用
filter_var($str, FILTER_VALIDATE_BOOLEAN)或严格比对再转换,不依赖 JSON 解析
真正难的不是写 json_decode(),而是你永远不知道传进来的是不是“看起来像 JSON”的字符串——BOM、编码混杂、半截 JSON、前端手拼字符串,这些都得在 decode 前兜住。多打一行 json_last_error_msg(),省掉半小时翻日志。











