
本文介绍如何使用 josson 库,根据 `users` 列表中每个元素的 `parent_user_id` 字段,将原始 json 对象按组拆分为多个结构相同但 `users` 子集不同的独立对象。
在实际开发中(尤其是处理 MongoDB 或其他文档型数据库返回的嵌套结构数据时),我们常遇到一种典型需求:保持外层对象不变,仅将内嵌的 List
虽然 Java 8+ 的 Stream API 可以完成基础分组,但面对深层嵌套、动态字段、多层级 JSON 结构时,手动映射和深拷贝易出错、可读性差且维护成本高。此时,专用 JSON 转换库能显著提升开发效率与健壮性。
推荐使用轻量、声明式、支持链式路径操作的 Josson 库(纯 Java 实现,无反射依赖,兼容 Android 和 Java SE)。它通过简洁的路径表达式即可完成复杂结构重组:
✅ 核心转换逻辑解析
以下 Josson 表达式实现了题目所需的全部行为:
立即学习“Java免费学习笔记(深入)”;
JsonNode result = josson.getNode(
"[]@" + // ① 将输入数组的每个顶层对象视为独立分支(支持批量处理)
".users" + // ② 进入 users 数组节点
".group(parent_user_id)" + // ③ 按 parent_user_id 分组 → 输出 Map>
".map(..._id, ...name, ...description, users:elements)" + // ④ 为每组构造新对象:从上两级取 _id/name/description;将当前分组结果(elements)重命名为 users
".@flatten()" // ⑤ 合并所有分支结果为单个扁平数组
); ? 提示:... 表示向上回溯层级(..._id 即取当前 users 元素所在父对象的 _id 字段),这是 Josson 处理父子上下文关联的关键语法。
✅ 完整示例代码(含依赖配置)
1. Maven 引入 Josson
com.octomix.josson josson 1.6.2
2. Java 转换代码
import com.octomix.josson.Josson;
import com.fasterxml.jackson.databind.JsonNode;
public class JsonSplitter {
public static void main(String[] args) {
String rawJson = "[{...}]"; // 替换为你的实际 JSON 字符串(见问题中 DB 返回格式)
Josson josson = Josson.fromJsonString(rawJson);
JsonNode transformed = josson.getNode(
"[]@.users.group(parent_user_id).map(..._id, ...name, ...description, users:elements).@flatten()"
);
System.out.println(transformed.toPrettyString());
}
}⚠️ 注意事项与最佳实践
- 字段容错性:若 description 可能缺失(如示例中为 null),Josson 默认保留原值,无需额外判空。
- 性能考量:Josson 内部采用流式解析与惰性求值,适合中等规模数据(万级以内 users 条目);超大数据建议结合分页或流式处理。
-
替代方案对比:
- 手动 Stream + Collectors.groupingBy:需定义 DTO、处理深拷贝、重建外层结构,代码量大且易漏字段;
- Jackson ObjectMapper + 自定义 JsonDeserializer:灵活性高但开发周期长,不适合快速原型;
- Josson:声明式、零模板代码、天然支持 JSON 路径导航,特别适合 ETL 场景。
- 扩展性提示:若后续需按多字段(如 parent_user_id + status)联合分组,只需改为 .group(parent_user_id, status)。
通过 Josson 的路径式转换,你可以在一行表达式中精准实现“外层复用、内层分组、结构重组”的复杂 JSON 拆分逻辑,大幅提升数据预处理的开发效率与可维护性。










