mysql 5.7+才支持原生json函数,低版本调用会报错;需用select version()确认版本,5.6.40及以下应升级或避免使用;json_object()要求键值成对、key为字符串、null字段被忽略;嵌套结构需结合json_arrayagg()与group by;自定义函数必须声明returns json并显式转换。

MySQL 5.7+ 才支持原生 JSON 函数
低于 5.7 的 MySQL 版本没有 JSON_OBJECT、JSON_ARRAY 等函数,强行调用会报错 FUNCTION xxx does not exist。必须先确认版本:
SELECT VERSION();如果返回值是
5.6.40 或更低,就别折腾 JSON 函数了——要么升级,要么用字符串拼接(不推荐,易注入、难解析)。
用 JSON_OBJECT() 构造键值对最稳妥
这是最常用也最安全的 JSON 返回方式,尤其适合从表字段动态生成对象。注意三点:
-
JSON_OBJECT()要求参数成对出现(key, value),奇数个参数会报错Incorrect number of arguments - key 必须是字符串字面量或表达式结果为字符串;若字段名含空格或特殊字符,得用引号包裹,比如
JSON_OBJECT("user name", name) - value 为 NULL 时,该字段会被自动忽略(不是输出
"key": null),如需保留 null 值,得显式用COALESCE(col, CAST(NULL AS JSON))
示例:从 users 表构造单条用户 JSON
SELECT JSON_OBJECT('id', id, 'name', name, 'email', email) AS user_json FROM users WHERE id = 123;
嵌套 JSON 要靠 JSON_OBJECT() 和 JSON_ARRAY() 组合
想返回带数组的结构(比如用户及其订单列表),不能只靠一层 JSON_OBJECT()。常见错误是试图在 SELECT 中直接 JOIN + GROUP BY 拼 JSON,结果重复或截断。
- 多对一(如用户+单个地址):用
(SELECT JSON_OBJECT(...))子查询关联 - 一对多(如用户+多个订单):必须用
JSON_ARRAYAGG(JSON_OBJECT(...))聚合,且需配合GROUP BY user_id - 聚合后字段别名要明确,否则外层 JSON_OBJECT 可能取不到值
示例:用户及订单列表(MySQL 8.0+ 支持窗口函数更稳,但 5.7 起 JSON_ARRAYAGG 已可用)
SELECT JSON_OBJECT(
'user', JSON_OBJECT('id', u.id, 'name', u.name),
'orders', JSON_ARRAYAGG(
JSON_OBJECT('order_id', o.id, 'amount', o.total)
)
) AS result
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.id = 123
GROUP BY u.id;
函数内返回 JSON 必须声明 RETURNS JSON
自定义函数想返回 JSON,声明类型不能写 TEXT 或 VARCHAR,否则调用时可能被自动转义或截断(尤其含 Unicode 或换行时)。
- 函数体里用
RETURN JSON_OBJECT(...)或RETURN @json_var(前提是 @json_var 是 JSON 类型变量) - 若中间用了字符串拼接再转 JSON,务必用
CAST(... AS JSON)显式转换,否则 MySQL 当作 TEXT 处理 - 调试时可先用
SELECT your_function(...)直接执行,看是否报Invalid JSON text—— 大概率是某个字段含非法控制字符或未转义引号
一个最小可用函数示例:
DELIMITER $$
CREATE FUNCTION get_user_json(uid INT)
RETURNS JSON
READS SQL DATA
DETERMINISTIC
BEGIN
RETURN (SELECT JSON_OBJECT('id', id, 'name', name)
FROM users WHERE id = uid);
END$$
DELIMITER ;
JSON 函数看着简单,但字段为空、类型隐式转换、聚合边界、函数返回类型声明这四点,任一出错都会让结果变成 NULL 或语法错误,而不是你预期的结构化数据。











