Laravel中json_decode报错:传入参数为对象而非字符串问题排查
解决json_decode参数为对象而非字符串的报错问题
我看你在Laravel 5.7 + PHP7.3环境下遇到了头疼的问题:把数组用json_encode转成JSON存到MySQL后,读取时调用json_decode却报错,提示参数是对象而非字符串。而且你发现移除存储内容里的反斜杠或者给数据库值加双引号后错误就消失了,咱们来一步步拆解解决。
核心原因分析
你遇到这个错误的关键其实是两点:
- Laravel对JSON字段的自动解析:如果你的
extrainfo字段用的是MySQL的JSON类型,Laravel在查询数据时会自动把这个字段的内容解析成PHP的StdClass对象(没设置$casts的话),而不是原始的JSON字符串。这时候你直接把这个对象传给json_decode,自然就会报“参数应为字符串”的错误。 - 双重JSON编码的坑:看你提供的存储内容,
CreditScoreFactor的值本身就是一个带反斜杠的转义JSON字符串,这说明你在存储前,$report['extrainfo']['CreditScoreFactor']已经是一个JSON字符串了,然后你又对整个$report['extrainfo']做了json_encode,导致最终存到数据库的是双重编码的JSON,这也给后续解析添了乱。
针对性解决方案
根据你的数据库字段类型,分两种情况处理:
情况1:数据库extrainfo字段是JSON类型(推荐)
这是Laravel设计时推荐的做法,完全不需要手动编码:
- 存储时:直接把数组赋值给模型属性,Laravel会自动帮你转成JSON存入数据库:
$reportData->extrainfo = !empty($report['extrainfo']) ? $report['extrainfo'] : null; $reportData->save(); - 读取时:Laravel会自动把JSON解析成PHP对象或数组,不需要再调用
json_decode。如果想直接得到数组,可以在模型里添加$casts属性:
之后读取时直接用即可:// 在你的ReportData模型中 protected $casts = [ 'extrainfo' => 'array', ];$extrainfo = $this->extrainfo; // 直接是数组,无需json_decode
情况2:数据库extrainfo字段是TEXT/VARCHAR类型
如果必须用文本类型存储:
- 存储时:确保只做一次JSON编码。如果
$report['extrainfo']['CreditScoreFactor']已经是JSON字符串,先把它解码成数组,再一起编码整个$report['extrainfo'],避免双重编码:if (!empty($report['extrainfo'])) { // 如果CreditScoreFactor是JSON字符串,先解码 if (isset($report['extrainfo']['CreditScoreFactor'])) { $report['extrainfo']['CreditScoreFactor'] = json_decode($report['extrainfo']['CreditScoreFactor'], true); } $reportData->extrainfo = json_encode($report['extrainfo'], JSON_UNESCAPED_SLASHES); } else { $reportData->extrainfo = null; } $reportData->save(); - 读取时:先确认拿到的是字符串(文本类型字段Laravel不会自动解析),再调用
json_decode:if ($extrainfo = $this->extrainfo) { // 先确保是字符串,再解码 $extrainfo = is_string($extrainfo) ? json_decode($extrainfo, true) : $extrainfo; }
验证步骤
- 先检查你的数据库
extrainfo字段类型,优先用JSON类型,更贴合Laravel的设计逻辑。 - 清理数据库中已存储的错误双重编码内容,重新存入正确的JSON或数组。
- 按照对应方案修改存储和读取代码,测试是否还会出现报错。
内容的提问来源于stack exchange,提问作者facebook-100003209134068
相关产品推荐
相关产品推荐

