mysql 5.7+ 应用 json_extract 提取嵌套字段最稳妥,需配合 json_unquote 去引号;-> 返回带引号字符串,->> 等价于 json_unquote(json_extract());非法 json 或 null 时返回 null,须用 json_valid() 预检。

MySQL 5.7+ 怎么用 JSON_EXTRACT 取出嵌套字段
直接用 JSON_EXTRACT 是最稳妥的方式,尤其当字段是合法 JSON 字符串(不是纯文本或 NULL)时。它返回带引号的 JSON 值(比如 "admin"),所以后续常要套 JSON_UNQUOTE 去掉双引号。
- 如果只取一层:用
JSON_EXTRACT(json_col, '$.role') - 取数组第 2 个元素:用
JSON_EXTRACT(json_col, '$[1]')(注意索引从 0 开始) - 取深层嵌套:路径支持点号和方括号混用,比如
'$.permissions[0].action' - 路径错误或字段不存在时,
JSON_EXTRACT返回NULL,不会报错 —— 这点容易误以为“取到了空字符串”
为什么 -> 操作符有时取不到值
-> 是 JSON_EXTRACT 的语法糖,但默认返回带引号字符串;而 ->> 才等价于 JSON_UNQUOTE(JSON_EXTRACT(...))。新手常卡在这一步,查出来全是 "user" 却以为是类型问题。
- 写
json_col->'$.name'→ 结果是"John"(含双引号) - 写
json_col->>'$.name'→ 结果是John(纯文本,可直接参与比较或连接) - 如果
json_col是TEXT或VARCHAR类型但内容不是合法 JSON,->会静默返回NULL,不报错也不提示格式问题 - MySQL 5.7 要求 JSON 字段必须通过
JSON_VALID()校验才被当作 JSON 处理,否则->当普通字符串切片,结果不可靠
JSON 字段为空、NULL 或格式错误怎么办
线上数据里 JSON 字段经常不干净:可能是空字符串 ''、NULL、'null'(字符串)、或者少个逗号的非法 JSON。这些都会让 JSON_EXTRACT 返回 NULL,但你得知道是哪一种。
- 先用
JSON_VALID(json_col)判断是否为合法 JSON,返回 0/1 - 再用
IF(JSON_VALID(json_col), JSON_EXTRACT(json_col, '$.id'), NULL)避免无效解析 - 别直接
WHERE json_col->>'$.status' = 'active'—— 如果字段非法,这一行会被跳过,你以为数据少了,其实是过滤掉了 - 临时修复可以用
UPDATE t SET json_col = NULL WHERE NOT JSON_VALID(json_col),但得确认业务是否允许丢弃
PostgreSQL 里怎么对应?别用 json_extract_path
PostgreSQL 没有 JSON_EXTRACT,但原生支持更直观的 -> 和 ->> 操作符,且对 NULL 和非法 JSON 更敏感:遇到非法 JSON 会直接报错 invalid input syntax for type json,而不是静默返回 NULL。
- 取字符串字段:
json_col ->> 'name'(自动去引号) - 取子对象:
json_col -> 'address'(返回 JSON 对象) - 取数组元素:
json_col -> 'tags' ->> 0(注意这里索引是字符串'0') - 想兼容 MySQL 行为?加
AND json_col IS NOT NULL AND json_typeof(json_col) = 'object'做前置判断
真正麻烦的是跨数据库迁移时,MySQL 的宽容(静默 NULL)和 PostgreSQL 的严格(报错)会让同一段 SQL 在两边表现完全不同。上线前一定在真实数据上跑一遍 JSON_VALID 或 json_typeof 检查。










