MySQL JSON_LENGTH 怎样分别统计对象成员和数组元素
来源:17golang原创
时间:2026-11-13 20:48:31 234浏览 收藏
MySQL 的 JSON_LENGTH() 不是计算 JSON 文本的字符数,而是计算一个 JSON 值的直接成员数量:数组返回元素数,对象返回成员数,标量返回 1。如果传入路径,就先定位路径对应的值,再按同一规则计数;路径不存在时返回 NULL。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/json-attribute-functions.html
因此,判断结果时先问“当前路径拿到的是什么类型”,再解释数字含义。嵌套对象和数组不会递归累加,统计的是当前值的第一层。
对象、数组和标量的长度规则
可以把 JSON_LENGTH() 看成一个直接层级计数器:
| JSON 值 | 返回含义 | 示例结果 |
|---|---|---|
| 数组 | 直接元素数量 | [10,20,{"a":3}] 返回 3 |
| 对象 | 直接键值成员数量 | {"a":1,"b":{"c":30}} 返回 2 |
| 标量 | 标量本身算一个值 | true 返回 1 |
| 嵌套对象或数组 | 只占一个直接成员位置 | 不会把内部成员继续相加 |

用最小 SQL 统计顶层对象和数组
先用字面量理解“直接层级”:
-- 分别观察数组、对象和标量;每个表达式都只统计当前值
SELECT
JSON_LENGTH('[10, 20, {"a": 3}]') AS array_count,
JSON_LENGTH('{"a": 1, "b": {"c": 30}}') AS object_count,
JSON_LENGTH('true') AS scalar_count;
预期含义是 3、2、1。数组中的对象只算数组的第三个元素;对象中的嵌套对象只算对象的第二个成员。若业务要求“所有嵌套节点总数”,JSON_LENGTH() 本身不是递归遍历器,需要改用明确的遍历方案。
在表字段上使用时,先给查询起一个清晰的别名,避免把 JSON 长度误当成字符串长度:
-- 读取订单扩展字段的顶层成员数;这里假设 extra_info 是 JSON 列 SELECT order_id, JSON_LENGTH(extra_info) AS top_level_member_count FROM order_demo WHERE order_id = 1001;
用 path 参数统计嵌套数组或对象
第二个参数是 JSON path。它不会改变计数规则,只决定计数对象从整个文档切换到某个子值:
-- 先取 payload.items 数组,再统计其中的直接元素
SELECT JSON_LENGTH(
'{"payload":{"items":[{"id":1},{"id":2}],"meta":{"source":"api"}}}',
'$.payload.items'
) AS item_count;
-- 统计 payload.meta 对象的直接成员;嵌套路径不存在时结果为 NULL
SELECT JSON_LENGTH(
'{"payload":{"items":[1,2],"meta":{"source":"api"}}}',
'$.payload.meta'
) AS meta_member_count;
第一个查询的目标值是数组,所以返回数组元素数;第二个目标值是对象,所以返回对象成员数。路径表达式必须合法,路径找不到值时返回 NULL,不能把它当作空数组的 0。

NULL、空容器和无路径结果要分开
实际排查中最容易混淆的是以下几种情况:
- 空数组
[]的长度是0。 - 空对象
{}的长度是0。 - 标量(例如字符串、数字、布尔值)长度是
1。 - SQL 参数为
NULL,或 path 没有定位到值时,返回NULL。 - JSON 文档或 path 表达式非法时会报错,而不是返回一个普通计数。
-- 用 IFNULL 只在业务明确允许时把“未找到”映射成 0
SELECT
JSON_LENGTH('{"items":[]}', '$.items') AS empty_array_count,
JSON_LENGTH('{"meta":{}}', '$.meta') AS empty_object_count,
JSON_LENGTH('{"items":[1]}', '$.missing') AS missing_path_count,
IFNULL(JSON_LENGTH('{"items":[1]}', '$.missing'), 0) AS missing_as_zero;
最后一列只是展示业务映射,不代表“路径不存在”天然等于“空集合”。如果后续逻辑需要区分“字段缺失”和“字段存在但为空”,请保留原始的 NULL,不要过早使用 IFNULL。
用 JSON_TYPE 确认数字到底代表什么
当 JSON 来自用户输入或旧数据时,建议把类型一起读出来。这样看到 1 时,能知道它是一个标量,还是包含一个元素的数组,还是只有一个成员的对象。
-- 同时读取目标值类型和长度,避免只看数字作错误推断
SET @doc = '{"value": [10], "meta": {"source": "api"}}';
SELECT
JSON_TYPE(JSON_EXTRACT(@doc, '$.value')) AS value_type,
JSON_LENGTH(@doc, '$.value') AS value_length,
JSON_TYPE(JSON_EXTRACT(@doc, '$.meta')) AS meta_type,
JSON_LENGTH(@doc, '$.meta') AS meta_length;
JSON_TYPE() 用来解释类型,JSON_LENGTH() 用来解释当前类型的直接数量。两者配合比单独输出长度更适合日志、数据清洗和接口字段排查。
常见误区与选择建议
| 现象 | 正确解释 | 处理建议 |
|---|---|---|
| 结果是 1 | 可能是标量,也可能是一个元素的数组或一个成员的对象 | 同时读取 JSON_TYPE |
| 嵌套数据没有全部累加 | 函数只统计当前值的直接层级 | 明确是否需要递归遍历 |
| 无路径返回 NULL | 路径没有定位到值,不等于空容器 | 按业务决定是否映射为 0 |
| 字符串很长但长度为 1 | JSON 字符串是一个标量 | 不要用 JSON_LENGTH 计算字符数 |
如果目标是统计对象字段数或数组元素数,直接使用 JSON_LENGTH(doc, path);如果目标是判断类型,追加 JSON_TYPE;如果目标是统计所有深层节点,先设计遍历和去重规则,不能把当前函数当作递归统计器。
JSON_LENGTH 能统计字符串字符数吗?
不能。字符串属于标量,按 JSON_LENGTH 的规则返回 1。字符数应使用适合字符串的函数,并先确认取出的值是否已经去掉 JSON 包装。
空数组和路径不存在为什么不能都当成 0?
空数组表示目标值存在但没有元素;路径不存在表示没有找到目标值。两者语义不同,只有业务明确不需要区分时才可以统一映射。
怎样统计嵌套数组的元素总数?
JSON_LENGTH 只统计指定数组这一层。如果数组元素内部还包含数组,需要先定义遍历层级,再选择 JSON_TABLE 或应用层递归等方案。
记住一句话:JSON_LENGTH 统计的是“当前 JSON 值的直接数量”,不是文本长度,也不是整棵树的节点总数。先用 JSON_TYPE 确认类型,再用 path 把计数范围缩小,最后决定是否保留 NULL 的语义。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习