PHP 5 和 PHP 7 的 json_decode() 行为一致,差异源于未显式传参 $assoc:不传时均返回 stdClass;传 true 返回数组,传 false 返回对象;常见错误是省略参数后误用数组语法访问对象,或错误依赖 json_last_error_msg() 的空字符串判断。

PHP 5 和 PHP 7 的 json_decode() 行为差异,是导致 piso(应为 json_decode 的误写或拼写混淆)结果不同的最常见原因 —— 不是函数名变了,而是返回值类型默认行为彻底改了。
为什么 json_decode() 在 PHP 5 和 PHP 7 返回值看起来“不同”
根本不是函数本身逻辑变化,而是 PHP 7 修复了历史遗留的松散行为:PHP 5 中 json_decode('{"a":1}') 默认返回 stdClass 对象;PHP 7 完全继承该行为,但开发者常误以为“变了”,其实是自己代码里没显式控制 $assoc 参数,又依赖了数组/对象混用的脆弱写法。
真正影响结果的是你是否传了第二个参数 $assoc:
-
json_decode($json, false)→ 总是返回stdClass(PHP 5 和 7 一致) -
json_decode($json, true)→ 总是返回关联数组(PHP 5 和 7 一致) -
json_decode($json)(无第二参数)→ PHP 5 和 7 都返回stdClass,但很多老项目用foreach遍历对象时没注意属性访问方式,升级后报Invalid argument supplied for foreach(),其实是对象没转成数组就直接遍历了
检查你代码里是否隐式依赖了数组访问语法
这类问题在处理 JSON 响应时高频出现,尤其调用第三方 API 后直接 $data['key'] 访问 —— 如果没加 true,$data 是对象,$data['key'] 就会静默失败或报错。
立即学习“PHP免费学习笔记(深入)”;
典型错误写法:
$data = json_decode($json); echo $data['name']; // PHP 7 报 Warning: Illegal string offset 'name'(如果 $data 是对象)
正确做法(明确意图):
- 要数组:用
json_decode($json, true) - 要对象:用
json_decode($json, false)或省略,然后用->name - 不确定来源?加类型判断:
is_array($data) ? $data['key'] : $data->key
PHP 7 还悄悄改了 json_last_error_msg() 的返回值类型
PHP 5.5+ 引入该函数,但 PHP 5 返回 string,PHP 7 仍返回 string,看似没变 —— 但实际中很多人在错误处理里写了 if (json_last_error_msg() === ''),而 PHP 7 在无错误时返回 'No error'(不是空字符串),导致条件永远不成立。
安全写法只有这一种:
if (json_last_error() === JSON_ERROR_NONE) {
// 解析成功
}
别依赖 json_last_error_msg() 做逻辑分支,它只适合日志输出。
兼容写法建议:别猜版本,显式声明意图
跨版本最稳的方式,是把 $assoc 当作必填参数来用,哪怕你习惯对象也写上 false。这样既可读又防升级踩坑。
- 旧代码扫描重点:
json_decode(后面有没有逗号?没有就补, true或, false - CI/CD 中加个简单检查脚本,grep 出所有未指定
$assoc的json_decode调用 - 如果用 Laravel、Symfony 等框架,它们封装的
json_decode通常已默认设true,但别假设 —— 看源码确认
类型模糊才是问题根源,不是 PHP 7 “变坏了”。只要每次调用都明确写清你要数组还是对象,5 和 7 就不会给你意外。











