Spring Boot中如何归一化含重复字段的JSON记录?
解决方案
没有现成的Java/Spring注解可以直接实现这种「抽取公共字段+封装差异字段为数组」的JSON结构转换,但可以结合Jackson序列化特性与自定义数据结构实现,代码简洁且性能可控。
1. 定义匹配目标结构的实体类
先创建两个实体类,分别对应顶层公共字段容器和差异字段的子项:
// 顶层响应实体,包含公共字段和子项数组 public class GroupedResponse { private String Field1; private String Field2; private String Field3; private String Field4; private List<Item> items; // 生成全参/必要构造器、getter/setter方法 } // 子项实体,仅包含差异字段 public class Item { private String Field5; private String Field6; private String Field7; private String Field8; // 生成全参/必要构造器、getter/setter方法 }
2. 实现数据分组与转换逻辑
从数据源获取原始记录列表后,通过Stream API完成分组和结构转换(若数据来自数据库,优先通过GROUP BY语句在数据库层面分组,降低内存处理压力):
// 假设原始数据列表为List<OriginalRecord> originalRecords // 按Field1~Field4分组,键为公共字段值的集合,值为对应原始记录列表 Map<List<Object>, List<OriginalRecord>> groupedRecords = originalRecords.stream() .collect(Collectors.groupingBy(record -> Arrays.asList(record.getField1(), record.getField2(), record.getField3(), record.getField4()) )); // 构造最终响应对象 GroupedResponse finalResponse = new GroupedResponse(); // 提取公共字段值(分组键即为公共字段的集合) List<Object> commonValues = groupedRecords.keySet().iterator().next(); finalResponse.setField1((String) commonValues.get(0)); finalResponse.setField2((String) commonValues.get(1)); finalResponse.setField3((String) commonValues.get(2)); finalResponse.setField4((String) commonValues.get(3)); // 将原始记录转换为子项列表 List<Item> itemList = groupedRecords.values().stream() .flatMap(List::stream) .map(record -> { Item item = new Item(); item.setField5(record.getField5()); item.setField6(record.getField6()); item.setField7(record.getField7()); item.setField8(record.getField8()); return item; }) .collect(Collectors.toList()); finalResponse.setItems(itemList);
3. 返回JSON响应
在Spring Boot控制器中直接返回GroupedResponse对象,Jackson会自动将其序列化为你需要的JSON格式:
@GetMapping("/grouped-data") public ResponseEntity<GroupedResponse> getGroupedData() { // 此处补充获取原始数据、执行转换逻辑的代码 GroupedResponse response = ...; return ResponseEntity.ok(response); }
性能优化提示
- 大数据量场景下,优先通过数据库
GROUP BY语句完成分组,避免在应用内存中处理大量数据。 - 可使用Jackson的
@JsonIgnore注解在原始实体中标记无需序列化的字段,或用@JsonProperty指定字段名,适配JSON结构要求。
内容的提问来源于stack exchange,提问作者Tim S.
相关产品推荐
相关产品推荐

