thinkphp json字段解析失败主因是未在模型中声明$jsonexception属性;需配置protected $json = ['config'],且不可与withattr重复使用,非模型查询须手动json_decode。

ThinkPHP 里 JSON 字段解析失败,基本不是框架坏了,而是你没告诉它“这个字段要当 JSON 解析”。默认情况下,哪怕数据库字段类型是 JSON,TP6 也只当它是字符串返回——$data->config 拿到的是一个带引号的 JSON 字符串,不是数组,直接 foreach 或 ->id 必然报错。
模型没声明 $json 属性
这是最常见原因:数据库存了 {"theme":"dark","lang":"zh"},但模型里没写 protected $json = ['config'];,查出来就是原样字符串。
-
$json是模型级配置,只对find()、select()等模型查询生效;用Db::table()->select()完全不走这套逻辑 - 字段名必须拼写完全一致,大小写敏感;不能写成
'Config'或'setting_config' - 不支持点号嵌套,比如
'user.profile'无效,只能填一级字段名 - 如果输出
string(28) "{"theme":"dark","lang":"zh"}",基本就是这一步漏了或拼错了
$json 和 withAttr 同时用了
两者机制冲突,叠加使用会导致重复解码或跳过处理。例如:
protected $json = ['setting']; protected $withAttr = ['setting' => 'json_decode'];
TP 先按 $json 自动 json_decode 一次,再进 withAttr 又调一次 json_decode——第二次作用在数组上,返回 null,数据就丢了。
- 优先选
$json:轻量、符合 TP 设计,写入时还自动json_encode - 只在需要定制逻辑时用
withAttr,比如兼容旧格式、加默认值 fallback - 删掉其中一个,别共存;检查模型里是否残留了历史写的
withAttr配置
原始 JSON 字符串本身非法
$json 配对了,字段也取到了,但 json_decode 仍失败——问题不在 TP,而在字符串内容本身。常见污染源:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- Windows 换行符
\r\n被当成普通字符(尤其从富文本或 Excel 导入) - UTF-8 BOM 头
\xEF\xBB\xBF开头,肉眼不可见 - 零宽空格
\xE2\x80\x8B、软连字符等隐形字符 - 数据库字段类型是
TEXT但内容被截断,结尾缺}或]
验证方法:取出原始字符串后立刻调 json_last_error_msg(),别只看 is_null() 结果;生产环境建议记录截取前 200 字符的原始片段。
非模型查询绕过了所有自动处理
用 Db::name('user')->field('id,config')->select() 或原生 SQL,$json 和 withAttr 全部失效。此时字段就是纯字符串,必须手动处理:
$rows = Db::name('user')->field('id,config')->select();
foreach ($rows as &$row) {
$row['config'] = json_decode($row['config'], true) ?: [];
}
注意:这里要自己判空、捕获错误,TP 不介入;如果字段可能为空或非法,务必加 json_last_error() === JSON_ERROR_NONE 校验。
真正容易被忽略的是——你以为字段“存的是 JSON”,其实它早被中间层(比如请求过滤、日志中间件、数据库触发器)悄悄改过;别急着改模型,先 var_dump($data->config) 看一眼原始值长什么样。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










