json_decode()默认返回stdClass对象,需传true参数才得关联数组;解析失败静默返回null,须用json_last_error()检查;输入必须为UTF-8无BOM;大JSON需防内存溢出。

json_decode() 默认返回对象,不是数组
直接调用 json_decode($json) 会返回 stdClass 对象,不是你想要的关联数组。很多 PHP 开发者卡在这一步,一打印发现是 object,用 $arr['key'] 报错 —— 因为对象得用 ->key 访问。
解决办法很简单:第二个参数传 true:
json_decode($json, true)
这样才真正转成 PHP 关联数组。注意这个 true 是布尔值,不是字符串 "true",也不是数字 1(虽然 PHP 会松散转换,但显式写 true 更安全、可读)。
解析失败时返回 null,必须检查错误
json_decode() 在 JSON 格式非法、编码不兼容(如含 BOM)、或超深度嵌套时,**静默返回 null**,不会抛异常。如果你没检查就直接用,后续操作大概率报 Trying to access array offset on value of type null 或 Call to a member function ... on null。
务必配合 json_last_error() 验证:
- 先调用
json_decode($json, true) - 再立即调用
json_last_error(),结果为JSON_ERROR_NONE才算成功 - 常见错误码:
JSON_ERROR_SYNTAX(语法错)、JSON_ERROR_UTF8(UTF-8 编码损坏,比如从 Windows 记事本复制的 JSON)
示例判断逻辑:
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new InvalidArgumentException('Invalid JSON: ' . json_last_error_msg());
}
中文乱码?确认输入是 UTF-8 且无 BOM
PHP 的 json_decode() 要求输入字符串必须是合法 UTF-8。如果 JSON 字符串本身含 GBK、ISO-8859-1 编码的中文,或文件开头有 UTF-8 BOM(\xEF\xBB\xBF),解析会失败或返回 null。
实操建议:
- 用
mb_detect_encoding($json, ['UTF-8', 'GB2312', 'GBK'], true)粗略检测编码(注意:不 100% 可靠,仅作参考) - 强制转 UTF-8:
$json = mb_convert_encoding($json, 'UTF-8', 'auto')(慎用,可能破坏原始数据) - 更稳妥做法:源头控制 —— 确保 JSON 来自 API 响应头带
Content-Type: application/json; charset=utf-8,或文件保存为「UTF-8 无 BOM」格式 - 快速去 BOM:
$json = ltrim($json, "\xEF\xBB\xBF")
深层嵌套或大 JSON 性能与内存注意点
json_decode() 是一次性加载整个字符串进内存并递归解析的。遇到几 MB 的 JSON(比如导出日志、全量商品数据),容易触发 memory_limit 错误,或解析极慢。
应对策略:
- 检查
memory_limit是否足够,必要时临时调整:ini_set('memory_limit', '256M') - 避免无意义的深度嵌套结构;前端传参时尽量扁平化
- 真要处理超大 JSON,考虑流式解析方案(如
jsonstream扩展或JsonReader类),但标准库不支持 - 调试时可用
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)美化输出,方便肉眼排查结构
最常被忽略的是:即使 JSON 看似“不大”,但含大量重复键或深层递归引用(虽然 JSON 规范不允许引用,但某些生成器会违规输出),也会导致解析器栈溢出或卡死 —— 这类问题只能靠 json_last_error() 捕获错误码 JSON_ERROR_DEPTH 或 JSON_ERROR_RECURSION 来定位。











