ThinkPHP 6.0 需在模型中声明 $json 属性(如 protected $json = ['config'];)才能自动将 JSON 字段转为数组/对象,否则查出为字符串;该配置仅对模型查询生效,不支持嵌套字段,且不可与同名 withAttr 冲突。

ThinkPHP 6.0 默认不会自动把数据库里的 JSON 字段转成 PHP 数组或对象,哪怕字段类型是 MySQL 的 JSON,查出来仍是字符串。直接 foreach 或用 ->key 访问就会报错,比如 Cannot use object as array。
确认模型中已声明 $json 属性
这是最常见也最关键的一步。必须在对应模型类里显式告诉 TP 哪些字段存的是 JSON:
- 写法:
protected $json = ['config', 'setting', 'extra']; - 字段名要和数据库列名完全一致(大小写敏感)
- 只支持一级字段名,不支持点号嵌套(如
user.info无效) - 该配置仅对
find()、select()等模型查询生效,Db::table()直接查不走模型逻辑,$json完全不起作用
验证是否真的被反序列化
出错时别猜,快速定位:
用于端到端视频本地化流程的轻量编排器,路由至四个专注子技能——/wjs-transcribing-audio、/wjs-translating-subtitles...
- 在访问字段前加一句:
var_dump(gettype($data->config), $data->config); - 如果输出
string和一串带引号的 JSON(如"{\"name\":\"张三\"}"),说明$json没配对或拼写错误 - 如果输出
array或object,说明已成功转义,问题可能出在后续访问方式上(比如用['name']访问对象)
避免与 withAttr 冲突
如果你同时用了 $json 和 $withAttr 处理同一个字段,容易互相覆盖:
立即学习“PHP免费学习笔记(深入)”;
- 例如:
protected $json = ['setting']; protected $withAttr = ['setting' => 'json_decode']; - TP 会先按
$json解一次,再进withAttr对数组又调一次json_decode,结果变成null - 建议二选一:
$json更轻量、推荐用于标准 JSON 字段;withAttr适合需要兼容旧格式、加默认值等定制逻辑的场景
写入时无需手动 json_encode
只要字段在 $json 列表里,TP 会在写入前自动调用 json_encode:
- 你传数组进去:
$model->config = ['theme' => 'dark', 'lang' => 'zh']; - TP 会自动转成 JSON 字符串存进数据库
- 注意:确保数据本身可被编码(不含资源、循环引用等),否则写入会失败且无提示


















