
本文介绍如何使用 gson 将含重复 action 字段的 json 数组(每个元素含独立 myobject)反序列化并转换为按 action 分组、myobject 为列表的新结构,适用于无法修改原始 json 的场景。
在实际 JSON 数据集成中,常遇到「结构不规范但不可修改」的情况:输入是一个对象数组,每个对象都包含相同的键(如 "action": "create")和一个独立的嵌套对象(如 "myObject"),而业务逻辑却要求将相同 action 对应的所有 myObject 合并为一个对象中的列表字段。标准反序列化器(如 Gson 或 Jackson)默认按字段一对一映射,无法直接实现“多对一聚合”,因此需采用两阶段处理策略:先以原始结构解析,再手动重组为目标结构。
核心设计:分离模型 + 显式聚合
我们定义三类 POJO,职责清晰、无耦合:
// 表示原始 JSON 中每个数组元素的结构
static class OriginalModel {
String action;
MyObjectData myObject;
}
// 表示目标输出结构:每个 action 对应一个含 myObject 列表的对象
static class TransformedModel {
String action;
List<MyObjectData> myObject;
public TransformedModel(String action, List<MyObjectData> myObject) {
this.action = action;
this.myObject = myObject;
}
}
// 嵌套数据实体
static class MyObjectData {
String name;
String description;
}✅ 注意:若这些类定义在非静态上下文中(如普通内部类),务必声明为 static,否则 Gson 反序列化时可能因隐式引用外部类实例而抛出 IllegalAccessException。
完整转换流程(Gson 实现)
以下代码完成从原始 JSON 字符串到聚合后 JSON 字符串的端到端转换:
Gson gson = new Gson();
// 第一步:按原始结构解析为 List<OriginalModel>
List<OriginalModel> originalList = gson.fromJson(json, new TypeToken<List<OriginalModel>>() {}.getType());
// 第二步:按 action 分组聚合 myObject(保持输入顺序)
Map<String, List<MyObjectData>> grouped = new LinkedHashMap<>();
for (OriginalModel item : originalList) {
grouped.computeIfAbsent(item.action, k -> new ArrayList<>()).add(item.myObject);
}
// 第三步:构建 TransformedModel 列表
List<TransformedModel> result = grouped.entrySet().stream()
.map(entry -> new TransformedModel(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
// 第四步:序列化为目标 JSON(可选:格式化输出便于调试)
String outputJson = gson.toJson(result);
// 若需单个对象而非数组(如题干示例末尾为 {} 而非 [{...}]),取 result.get(0) 即可关键细节与注意事项
- 顺序保证:使用 LinkedHashMap 而非 HashMap,确保聚合结果中 action 的出现顺序与原始 JSON 数组一致;
- 空值安全:computeIfAbsent 自动处理首次插入,无需额外判空;
-
Jackson 兼容方案:若项目强制使用 Jackson,可替换为 ObjectMapper.readValue(json, new TypeReference
- >(){}),后续聚合逻辑完全一致;
- 扩展性提示:若未来需支持多 action 类型(如 "create"/"update"/"delete")分别输出,当前 grouped 结构天然支持;若需扁平化为单个 TransformedModel(而非列表),仅需校验 grouped.size() == 1 后取首项;
- 性能考量:该方案时间复杂度为 O(n),空间复杂度为 O(n),适用于万级以内数据;超大规模场景建议流式解析(如 Gson 的 JsonReader)避免全量加载。
通过模型解耦与显式聚合,我们绕过了反序列化器对「重复键」的固有限制,以清晰、可控、可测试的方式达成了结构重塑目标——这正是面对遗留或第三方 JSON 接口时,稳健集成的关键实践。










