登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL JSON_UNQUOTE 怎样去掉 JSON 字符串外层引号

来源:17golang原创

时间:2026-10-28 23:15:58 209浏览 收藏

如果 JSON 字段里的字符串拿到应用层后变成了 "Alice",而不是你想要的 Alice,通常需要的是 JSON_UNQUOTE()。它会按 JSON 字符串规则去掉外层双引号并处理转义;但数组、对象等非字符串值不会凭空变成普通文本。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/json-modification-functions.html#function_json-unquote

我在整理 JSON 查询结果时,最容易混淆的是三层引号:SQL 语句的字符串字面量、JSON 字符串自己的双引号,以及应用层最终要消费的文本。下面按这三层关系,把取值、转义和边界拆开。

JSON_UNQUOTE 到底去掉了什么

JSON_UNQUOTE(json_val) 接收一个 JSON 值,返回 utf8mb4 字符串。输入是 JSON 字符串时,结果会去掉字符串值的外层双引号;输入是数组或对象时,结果仍然是它们的 JSON 文本表示,不应把它理解成“所有 JSON 都转成业务字符串”。

JSON 文档、JSON_EXTRACT、JSON_UNQUOTE 与普通字符串及数组对象之间的值类型边界说明图
图1:值类型边界说明图,查看 JSON_EXTRACT、JSON_UNQUOTE 与数组/对象结果之间的静态关系;这是说明图,不是运行截图。

例如下面的 SQL 中,最外层单引号属于 SQL 字符串字面量,里面的双引号才是 JSON 字符串的一部分:

-- SQL 单引号包住输入,JSON 双引号包住字符串值
SET @name_json = '"Alice"';

-- JSON_UNQUOTE 去掉 JSON 字符串的外层双引号
SELECT JSON_UNQUOTE(@name_json) AS name_text;

-- 数组不是 JSON 字符串,结果仍保持数组文本
SELECT JSON_UNQUOTE('[1, 2, 3]') AS array_text;

第一个结果是普通文本 Alice,第二个结果仍是 [1, 2, 3]。因此,如果应用只需要姓名、状态码这类标量字段,JSON_UNQUOTE 很合适;如果需要继续访问数组元素,则应保留 JSON 值交给后续 JSON 函数。

从 JSON_EXTRACT 取字段时,为什么常常还要再解引号

JSON_EXTRACT() 返回的是 JSON 值。对字符串字段来说,它通常带着 JSON 引号;把结果直接交给普通 SQL 文本或应用响应,就容易出现“多了一层引号”的感觉。可以把显式写法和快捷操作符放在一起比较:

-- 建立一个包含字符串、数字和数组的 JSON 文档
SET @doc = '{"name":"Alice","age":30,"tags":["go","mysql"]}';

-- JSON_EXTRACT 返回 JSON 字符串值,字符串仍带 JSON 引号
SELECT JSON_EXTRACT(@doc, '$.name') AS json_name;

-- 显式去掉字符串外层引号
SELECT JSON_UNQUOTE(JSON_EXTRACT(@doc, '$.name')) AS plain_name;

-- ->> 是“取路径并取消引用”的常用简写
SELECT @doc->>'$.name' AS plain_name_short;

-- 数字与数组不应套用“去引号后就是普通文本”的假设
SELECT JSON_UNQUOTE(JSON_EXTRACT(@doc, '$.age')) AS age_value,
       JSON_UNQUOTE(JSON_EXTRACT(@doc, '$.tags')) AS tags_value;

这里的判断重点不是函数名长短,而是输出类型:name 是 JSON 字符串,适合得到普通文本;age 是 JSON 数字,tags 是 JSON 数组,输出仍应按 JSON 值理解。若 SQL 只是把标量字段投影给应用层,我会优先使用 ->> 或显式组合;若要表达每一步的类型变化,显式写法更容易排查。

转义字符和 SQL 模式要一起看

JSON_UNQUOTE 不只是删除两个双引号。MySQL 会识别 JSON 字符串中的部分转义序列,例如 \\n、\\t、\\\"、\\\\ 和 \\uXXXX。这些序列是否按反斜杠转义解释,还会受到会话 SQL 模式 NO_BACKSLASH_ESCAPES 的影响。

JSON_UNQUOTE 处理反斜杠转义、Unicode 转义、SQL 模式与应用层文本的依赖边界说明图
图2:转义规则说明图,查看反斜杠序列、SQL 模式与输出文本的静态关系;不代表实际执行结果。
-- 输入明确成为 JSON 字符串,并包含制表符与 Unicode 转义
SELECT JSON_UNQUOTE('"\\t\\u0032"') AS decoded_text;

-- 检查当前会话模式;它会影响反斜杠的解释方式
SELECT @@sql_mode AS current_sql_mode;

-- 比较模式差异时,只在当前会话临时设置并恢复原值
SET @old_mode = @@sql_mode;
SET SESSION sql_mode = 'NO_BACKSLASH_ESCAPES';
SELECT JSON_UNQUOTE('"\\t\\u0032"') AS literal_mode_text;
SET SESSION sql_mode = @old_mode;

如果换行、制表符或 Unicode 字符的结果与预期不同,先确认输入到底是 JSON 文本还是已经被客户端解析过的文本,再确认会话是否启用了 NO_BACKSLASH_ESCAPES。不要在应用层盲目再做一次反转义,否则可能把原本正确的反斜杠再次改写。

四个边界决定是否应该使用 JSON_UNQUOTE

输入情况适合的判断注意点
JSON 字符串使用 JSON_UNQUOTE 或 ->>去掉 JSON 外层引号并处理规定的转义
数组或对象保留 JSON 值,继续用 JSON 函数不要把 JSON 文本当成已解析的业务字段
SQL NULL先处理 NULL 语义JSON_UNQUOTE(NULL) 返回 NULL
带引号但不是合法 JSON 字符串先修正输入或检查生成端可能直接产生错误,不能靠函数强行剥皮

实践中我会把“去掉 JSON 引号”和“把值转换成业务类型”分成两个动作。JSON_UNQUOTE 解决的是 JSON 字符串表示层;如果业务字段还需要日期、整数或布尔语义,应再使用明确的类型转换,并在接口契约里说明空值和非法值如何处理。

常见追问

JSON_UNQUOTE 能把 JSON 数组转换成逗号分隔字符串吗?

不能把它当成数组格式化函数。它对数组会保留 JSON 数组文本;如果要逐个元素处理,应使用 JSON_TABLE 或路径访问,再按业务规则聚合。

JSON_EXTRACT 和 ->> 应该选哪一个?

需要保留 JSON 类型、继续做 JSON 运算时使用 JSON_EXTRACT;只把字符串标量投影为普通文本时,显式的 JSON_UNQUOTE(JSON_EXTRACT(...)) 或 ->> 更直接。

为什么同一条 JSON_UNQUOTE 在不同环境输出不同?

优先检查输入是否经过了客户端转义,以及当前会话的 sql_mode 是否包含 NO_BACKSLASH_ESCAPES。JSON 转义和 SQL 字符串转义是两层规则,不能只看最终 SQL 表面。

一句话总结:JSON_UNQUOTE 负责把 JSON 字符串值还原为可消费的普通文本,不负责把所有 JSON 类型都扁平化。先确认字段是字符串、数字还是数组对象,再决定使用显式组合、->> 或继续保留 JSON 值,后续排查会清晰很多。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>