json_decode() 返回 null 主因是BOM、非UTF-8编码或未检查返回值;需trim控制字符、转码UTF-8并用json_last_error()校验;$assoc参数决定返回数组或对象,影响访问方式与错误行为。

json_decode() 解析失败,八成不是 JSON 写错了,而是字符串开头多了 BOM、编码不是 UTF-8、或者没检查返回值就直接用了。
为什么 json_decode() 返回 null 却不报错
它默认静默失败,只返回 null,连 warning 都不抛——尤其当输入含 UTF-8 BOM(\xEF\xBB\xBF)或 GBK 编码中文时。
常见现象:var_dump(json_decode($str)) 打印 null,但 json_last_error() 可能是 JSON_ERROR_SYNTAX 或更隐蔽的 JSON_ERROR_UTF8。
必须加校验:
- 用
trim($str, "\x00..\x1F\x7F")清掉控制字符 - 或强制转码:
$str = mb_convert_encoding($str, 'UTF-8', 'auto') - 解析后立刻检查:
if (json_last_error() !== JSON_ERROR_NONE) { echo json_last_error_msg(); }
json_decode() 第二个参数 $assoc 怎么选
这不是风格偏好,是结构契约:
传 true → 返回关联数组,支持 $data['name']、isset($data['name'])、foreach 直接遍历;
传 false(默认)→ 返回 stdClass 对象,必须用 $data->name,且 isset($data['name']) 会出错。
关键差异:
- 重复 key(如多个
"id"):对象模式只留最后一个;数组模式保留全部,按顺序存为数字索引 - 字段缺失时:
$obj->missing触发 Notice;$arr['missing']触发 Warning(可用isset()或array_key_exists()避免) - PHP 7.4+ 若启用
JSON_THROW_ON_ERROR,必须配try/catch,否则直接 fatal error
嵌套 JSON 字段里还藏着 JSON 字符串怎么办
比如数据库字段 payload 存的是 "{\"status\":\"ok\"}" ——json_decode() 不会自动递归解析它,你得手动再解一次。
安全做法:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
立即学习“PHP免费学习笔记(深入)”;
- 先用
json_decode($raw, true)得到顶层数组 - 对疑似 JSON 的字段(如
$data['payload']),先判断是否以{或[开头:ltrim($data['payload'])[0] === '{' || ltrim($data['payload'])[0] === '[' - 再单独调用:
json_decode($data['payload'], true) - 避免无脑递归:每层
json_decode()都要全量扫描字符串,数据大、嵌套深时性能明显下降
从文件读 JSON 时最容易漏的三件事
file_get_contents('config.json') 拿到的不一定是干净字符串:
- 文件本身带 BOM?用
hexdump -C config.json | head看前几个字节是不是ef bb bf - 文件权限够吗?
is_readable('config.json')必须为true,否则file_get_contents返回false,传给json_decode就是解析空字符串 - 路径写错?相对路径基于当前工作目录(
getcwd()),不是脚本所在目录(__DIR__),建议显式拼接:file_get_contents(__DIR__ . '/config.json')
实际中最容易被跳过的,是“清洗输入”这一步——哪怕只是多了一个不可见字符,json_decode() 就会放弃治疗。别信“我 JSON 肯定是对的”,先 var_dump(bin2hex($str)) 看前 10 字节。


















