
本文介绍在无法修改原始 json 的前提下,利用 gson 实现“按 `action` 字段归并多个 `myobject` 为单个列表”的反序列化转换方案,通过两阶段解析(先转原始模型,再手动聚合)达成目标输出。
在实际 JSON 数据集成场景中,常遇到结构不规范但又不可修改的输入源——例如同一数组中多个对象均携带相同 action 键(如 "create"),且各自关联独立的 myObject 子对象。此时若期望将所有同 action 的 myObject 聚合为一个列表(而非逐个映射为独立对象),标准反序列化器(如 Gson 或 Jackson)无法直接支持,因为其默认行为是按字段一对一绑定,不具备跨对象聚合能力。
解决该问题的核心思路是解耦解析与建模:不强行让单一 Java 类同时兼容输入结构与输出结构,而是分两步处理:
- 解析阶段:定义轻量级原始模型(OriginalModel),忠实映射输入 JSON 的扁平数组结构;
- 转换阶段:在内存中按 action 分组聚合 myObject,构造符合目标格式的 TransformedModel;
- 序列化阶段:将转换后的对象重新序列化为所需 JSON。
以下是完整可运行的实现示例(基于 Gson 2.10+):
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.*;
// 原始 JSON 对应的结构(一一映射输入)
static class OriginalModel {
String action;
MyObjectData myObject;
}
// 目标输出对应的结构(action + myObject 列表)
static class TransformedModel {
String action;
List<MyObjectData> myObject;
TransformedModel(String action, List<MyObjectData> myObject) {
this.action = action;
this.myObject = myObject;
}
}
// myObject 内部数据结构
static class MyObjectData {
String name;
String description;
}执行转换逻辑:
Gson gson = new Gson();
String json = "[\n" +
" {\"myObject\": {\"name\": \"foo\", \"description\": \"bar\"}, \"action\": \"create\"},\n" +
" {\"myObject\": {\"name\": \"baz\", \"description\": \"qux\"}, \"action\": \"create\"}\n" +
"]";
// Step 1: 解析为原始模型列表
Type originalType = new TypeToken<List<OriginalModel>>() {}.getType();
List<OriginalModel> originalList = gson.fromJson(json, originalType);
// Step 2: 按 action 分组聚合 myObject(保持原始顺序)
Map<String, List<MyObjectData>> grouped = new LinkedHashMap<>();
for (OriginalModel item : originalList) {
if (item.action != null && item.myObject != null) {
grouped.computeIfAbsent(item.action, k -> new ArrayList<>()).add(item.myObject);
}
}
// Step 3: 构造目标模型列表
List<TransformedModel> transformedList = grouped.entrySet().stream()
.map(entry -> new TransformedModel(entry.getKey(), entry.getValue()))
.toList();
// Step 4: 序列化为最终 JSON(即所需输出格式)
String resultJson = gson.toJson(transformedList);
System.out.println(resultJson);
// 输出:[{"action":"create","myObject":[{"name":"foo","description":"bar"},{"name":"baz","description":"qux"}]}]✅ 关键注意事项:
- LinkedHashMap 确保 action 分组顺序与输入数组中首次出现顺序一致;
- 所有嵌套类建议声明为 static,避免隐式持有外部类引用导致序列化异常;
- 若输入 JSON 中存在多种 action 值(如 "create" 和 "update"),本方案会自动生成多个 TransformedModel 实例,完全符合语义;
- 此方法不依赖任何特殊注解或反序列化配置(如 @JsonAnySetter 或 ACCEPT_SINGLE_VALUE_AS_ARRAY),规避了配置失效风险,具备强健性与可调试性;
- 如需 Jackson 实现,逻辑完全一致,仅需替换为 ObjectMapper + TypeReference
- > 即可。
该方案以清晰的职责分离和显式的转换逻辑,兼顾可读性、可维护性与兼容性,是处理“非标准 JSON 聚合需求”的推荐实践。










