
本文介绍如何利用 josson 库对 java 中嵌套在对象内的用户列表(arraylist)按 `parent_user_id` 字段进行分组拆分,将原单一对象转换为多个结构一致、仅 `users` 子数组不同的新对象。
在实际业务开发中(如权限管理、多租户用户聚合等场景),常需将一个包含嵌套用户集合的对象,依据其内部元素的某个共性字段(如 parent_user_id)进行逻辑“切片”——即保持外层元数据(如 _id、name、description)完全不变,仅将 users 数组按该字段值分组,生成多个独立对象。这种操作若手动遍历 + Map 分组 + 对象重建,代码冗长且易出错;而借助专为 JSON 转换设计的轻量级库 Josson,可仅用一行声明式表达式完成整个转换。
✅ 核心思路:声明式 JSON 流式变换
Josson 提供类似 SQL/函数式编程的链式语法,上述需求可分解为 5 步原子操作:
- []@ —— 将输入数组的每个顶层对象视为独立处理分支;
- .users —— 进入每个对象的 users 字段(即目标 ArrayList);
- .group(parent_user_id) —— 对 users 内部元素按 parent_user_id 值分组,生成 { "63a880...da": [user1, user2, ...], ... } 结构;
- .map(..._id, ...name, ...description, users:elements) —— 对每个分组结果映射为新对象:... 表示向上回溯两层(即原始对象),提取 _id/name/description;elements 是 Josson 为分组后子数组自动提供的别名,重命名为 users;
- .@flatten() —— 合并所有分支结果,并展平嵌套层级,输出标准 JSON 数组。
? 完整代码示例
import com.octomix.josson.Josson;
import com.fasterxml.jackson.databind.JsonNode;
// 假设 josson 已通过 Maven 引入:compile 'com.octomix.josson:josson:1.7.1'
String jsonInput = "[{ \"_id\": \"63a8808652f40e1d48a3d1d7\", \"name\": \"A\", \"description\": null, \"users\": [...] }]";
Josson josson = Josson.fromJsonString(jsonInput);
JsonNode result = josson.getNode(
"[]@" +
".users" +
".group(parent_user_id)" +
".map(..._id, ...name, ...description, users:elements)" +
".@flatten()"
);
System.out.println(result.toPrettyString());⚠️ 注意事项与最佳实践
- 字段一致性保障:确保所有待处理对象的外层字段名(如 _id, name)统一,且 users 字段始终为 List
- 空值安全:Josson 默认忽略 null 字段(如 description: null 会原样保留),无需额外判空;但若 users 可能为 null,建议预处理或在 .users 前加条件判断(如 ?users);
- 性能考量:Josson 基于 Jackson 构建,内存占用低、解析快,适合中等规模数据(万级以内 users 元素);超大规模建议结合流式处理(JsonParser)+ 手动分组;
- 替代方案对比:纯 Java 8 Stream 实现需嵌套 Collectors.groupingBy + Collectors.mapping + 深拷贝外层对象,代码量增加 3–5 倍,且难以维护复杂嵌套路径。
通过 Josson 的声明式语法,原本需要数十行 Java 代码的嵌套分组拆分任务,被浓缩为清晰、可读、可复用的一行表达式——这正是现代 JSON 处理工具提升开发效率的核心价值。










