json_decode()返回null的常见原因包括:json语法错误(如尾逗号、单引号)、非utf-8编码(含bom或gbk)、嵌套超深(默认512层)、含不可见控制字符(如零宽空格)、空字符串或null输入。

json_decode() 返回 null 的常见原因
PHP 中 json_decode() 返回 null,几乎一定是 JSON 字符串本身不合法,或编码/上下文问题导致解析失败,而不是函数“出错了”。PHP 不会抛异常,而是静默返回 null,这点容易让人误判。
最直接的验证方式是调用 json_last_error() 和 json_last_error_msg():
var_dump(json_decode($json)); // 可能输出 NULL var_dump(json_last_error()); // 比如 int(4) → JSON_ERROR_SYNTAX var_dump(json_last_error_msg()); // string(12) "Syntax error"
- 错误码
4(JSON_ERROR_SYNTAX)占绝大多数,说明 JSON 格式有硬伤:比如中文没 UTF-8 编码、末尾多逗号、单引号代替双引号、BOM 头、换行符未转义等 - 如果输入是
null或空字符串,json_decode()也返回null(注意:空字符串不是合法 JSON) -
json_decode('', true)同样返回null,不是因为参数问题,而是输入本身无效
中文字符和 BOM 导致解析失败
从文件读取、数据库取出、或前端 POST 过来的 JSON,若含中文且来源非 UTF-8(如 GBK),或文件开头存在 UTF-8 BOM(\xEF\xBB\xBF),json_decode() 会直接失败。
检查并清理 BOM 的安全做法:
$json = file_get_contents('data.json');
$json = preg_replace('/^\xEF\xBB\xBF/', '', $json); // 去 BOM
$data = json_decode($json, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
throw new InvalidArgumentException('Invalid JSON: ' . json_last_error_msg());
}
- 不要依赖
mb_convert_encoding($json, 'UTF-8', 'auto')自动识别,它可能把乱码“转”得更错 - 用
mb_detect_encoding($json, ['UTF-8', 'GBK', 'BIG5'], true)判断后,再显式转换(仅当确认源编码时才转) - 数据库字段若为
TEXT且连接未设charset=utf8mb4,查出的 JSON 字符串可能已损坏
json_decode($json, true) 和 false 的行为差异
第二个参数决定返回 array 还是 stdClass 对象,但它**不影响是否返回 null**。无论传 true 还是 false,只要 JSON 无效,结果都是 null。
但要注意一个易混淆点:
-
json_decode('{}', false)→stdClass对象,不是array -
json_decode('{}', true)→array() - 如果原始 JSON 是
{"0":"a","1":"b"},json_decode(..., true)仍返回关联数组,不会自动变成数字索引数组 —— PHP 不做键类型推断 - 嵌套过深(默认 512 层)或超大字符串(受
memory_limit限制)也可能导致失败,错误码为JSON_ERROR_DEPTH或内存耗尽
调试 JSON 输入的实用技巧
别只看 var_dump($json) —— 它会隐藏不可见字符。真正有效的检查步骤是:
- 用
bin2hex(substr($json, 0, 6))查前几个字节,确认有没有 BOM(efbbbf) - 用
json_encode(json_decode($json), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)尝试“重序列化”,若失败说明原串有问题;若成功,对比前后差异可发现空格、换行等格式差异 - 把变量写入临时文件:
file_put_contents('/tmp/debug.json', $json);,再用命令行jq . /tmp/debug.json验证(jq对格式极其敏感,报错即准) - 若来自
$_POST或php://input,先检查strlen($json)是否为 0,再确认get_headers('php://input', 1)或apache_request_headers()中Content-Type是否含application/json
真正棘手的情况往往不是语法错,而是 JSON 看似正常,实则混入了零宽空格(\xE2\x80\x8B)、软连字符(\xC2\xAD)这类 Unicode 控制字符 —— 它们在编辑器里不可见,却足以让 json_decode() 拒绝解析。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











