MySQL JSON字段在PHP中返回NULL,主因是PDO默认以字符串形式返回JSON类型,需显式调用json_decode()解析;若含BOM或编码错误,再配合json_last_error()排查。

PHP读取MySQL JSON字段时为什么返回NULL?
不是数据丢了,大概率是没用对 json_decode() 或字段本身被当成了字符串。MySQL的JSON类型在PDO默认情况下会以字符串形式返回,哪怕表结构定义为 JSON,PHP也收不到自动解析后的数组。
常见错误现象:$row['config'] === '{"theme":"dark","lang":"zh"}'(字符串),但直接 echo $row['config']['theme'] 会报错或输出空字符。
- 必须显式调用
json_decode($row['config'], true)才能得到关联数组 - 注意检查
json_last_error(),避免因字段含非法转义或BOM导致解析失败 - 如果用的是 MySQLi,记得开启
MYSQLI_OPT_INT_AND_FLOAT_NATIVE(对JSON无效,但常被误以为有关)
写入JSON字段前要不要先 json_encode()?
要,而且必须做。MySQL不接受PHP数组,只接受格式合法的JSON字符串。直接把数组塞进 INSERT 或 UPDATE 语句里,结果通常是 Array 字符串或SQL语法错误。
使用场景:保存用户偏好、动态表单数据、API响应缓存等。
立即学习“PHP免费学习笔记(深入)”;
- 推荐写法:
$data = ['theme' => 'light', 'notifications' => true]; $json_str = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - 务必校验编码结果:
if ($json_str === false) { throw new InvalidArgumentException('Invalid JSON: ' . json_last_error_msg()); } - 不要依赖PDO的自动类型转换——它对JSON类型字段不生效
用 JSON_EXTRACT 在SQL里查JSON字段值靠谱吗?
靠谱,但只适合简单查询,且要注意路径语法和返回类型。比如 JSON_EXTRACT(config, '$.theme') 返回带双引号的字符串 "dark",不是纯值。
性能影响:对大表执行 JSON_EXTRACT 无法使用索引,除非建生成列+索引(MySQL 5.7+)。
- 想查纯值,用
JSON_UNQUOTE(JSON_EXTRACT(config, '$.theme')) - 想查是否存在某个键,用
JSON_CONTAINS_PATH(config, 'one', '$.lang') - 更新部分字段更推荐应用层全量读-改-写,而非
JSON_SET—— 容易漏掉并发覆盖
PHP 8.1+ 的 PDO::ATTR_EMULATE_PREPARES 对JSON字段有影响吗?
有,而且是隐性坑。设为 true(默认)时,PDO会把所有绑定参数转成字符串再拼SQL,JSON字段可能被多加一层引号,最终存成 "{\"theme\":\"dark\"}"(即JSON字符串里的JSON字符串)。
正确做法是关掉模拟预处理,并确保MySQL连接使用原生准备语句:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);- 确认MySQL版本 ≥ 5.7 且启用了
mysql_native_password认证(旧版caching_sha2_password在某些PDO配置下会退化为模拟) - 写入前用
is_string($json_str) && json_validate($json_str)(PHP 8.3+)或手动json_decode()校验
\uXXXX;还有就是把JSON当万能筐,结果连 WHERE config->>'$.status' = 'active' 这种基本查询都忘了加索引。



















