
本文介绍一种更简洁、类型安全且可维护的方式,使用jackson库将对象列表按id分组并生成符合要求的嵌套json结构,避免手动拼装map与objectnode,提升代码健壮性与可读性。
本文介绍一种更简洁、类型安全且可维护的方式,使用jackson库将对象列表按id分组并生成符合要求的嵌套json结构,避免手动拼装map与objectnode,提升代码健壮性与可读性。
在实际开发中,将Java对象列表转换为特定结构的JSON(尤其是含分组聚合与嵌套数组)时,直接操作ObjectNode/ArrayNode或滥用MultiValueMap
✅ 推荐实现:DTO建模 + 分组流式转换
首先,定义清晰的目标JSON结构对应的Java DTO:
public static class InputItem {
private long id; // 对应 Origin ID
private String state; // 原 state 字段
private String local; // 原 local 字段
private long number; // 原 number 字段
// 构造函数、getter/setter(Lombok可简化)
}
public static class OutputItem {
private long id; // ObjectVO.id
private String observation; // ObjectVO.code(重命名语义)
private List<inputitem> input; // 聚合的子项列表
// 构造函数、getter/setter
}</inputitem>
接着,使用Java 8 Stream完成分组与映射(无需中间Map容器):
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
// 假设 voList 是原始 ObjectVO 列表
Map<long list>> grouped = voList.stream()
.collect(Collectors.groupingBy(ObjectVO::getId));
List<outputitem> result = grouped.entrySet().stream()
.map(entry -> {
Long id = entry.getKey();
List<objectvo> items = entry.getValue();
String observation = items.get(0).getCode(); // 同id下code一致,取首个
List<inputitem> inputList = items.stream()
.map(vo -> new InputItem(
vo.getIdOrigin(), // 注意:原数据中为 "Origin id" / "Origin ID"
vo.getState(),
vo.getLocal(),
vo.getNumber()
))
.collect(Collectors.toList());
return new OutputItem(id, observation, inputList);
})
.collect(Collectors.toList());
// 序列化为格式化JSON字符串
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String jsonOutput = mapper.writeValueAsString(result);</inputitem></objectvo></outputitem></long>
⚠️ 关键注意事项
- 字段名一致性:原始数据中存在 Origin id / Origin ID 大小写混用,建议在ObjectVO中统一getter为getIdOrigin(),避免运行时反射失败;
- 空值防护:若voList可能为空或items为空,应在map()前添加filter(e -> !e.getValue().isEmpty());
- 性能考量:groupingBy默认使用HashMap,对万级数据足够高效;如需并发处理,可替换为Collectors.groupingByConcurrent(...);
- JSON字段映射:目标结构中input数组内字段名为id/state/local/number,但示例输出误写为up/series——请严格按需求调整DTO字段名及JSON序列化别名(可用@JsonProperty("up"));
- 避免重复创建ObjectMapper:应将ObjectMapper声明为static final单例,防止资源浪费与线程安全问题。
✅ 总结
相比原始代码中手动构建MultiValueMap、逐层put()到ObjectNode的脆弱方式,本方案通过:
- 显式DTO建模明确数据契约;
- Stream.collect(groupingBy)天然支持分组聚合;
- Jackson自动序列化保障JSON结构零偏差;
- 零反射调用、强类型检查、易于单元测试。
不仅显著降低出错概率,也为后续扩展(如增加过滤条件、字段校验、异步批处理)奠定坚实基础。对于复杂JSON转换场景,“先建模,再流式转换,最后序列化” 应作为标准实践。










