Apache Camel Java实现JSON数组按唯一ID分组的格式转换方案
按ID分组处理JSON的Java实现方案
需求说明
我有如下JSON输入请求,需要按ID参数进行分组处理:
输入示例
[ { "ID": "1234", "CustomerName": "KUMAR", "BranchName": "HARBOUR", "SchemeName": "GOLD", "MobileNumber": "123456789", "CustomerType": "PRIMARY", "DedupeFound" : "NO" }, { "ID": "1234", "CustomerName": "SEAN", "BranchName": "HARBOUR", "SchemeName": "GOLD", "MobileNumber": "123456789", "CustomerType": "SECONDARY", "DedupeFound" : "YES" }, { "ID": "5678", "CustomerName": "MARK", "BranchName": "CANTONMENT", "SchemeName": "DIAMOND", "MobileNumber": "123456789", "CustomerType": "PRIMARY", "DedupeFound" : "NO" }, { "ID": "5678", "CustomerName": "STEVE", "BranchName": "CANTONMENT", "SchemeName": "DIAMOND", "MobileNumber": "123456789", "CustomerType": "SECONDARY", "DedupeFound" : "YES" } ]
转换规则
- 首先按ID字段分组,每组外层仅展示CustomerType为PRIMARY的主客户的基础字段信息
- 每个ID对应记录内新增DedupeDetails数组,存放该ID下所有客户的去重相关字段信息
期望输出示例
[ { "ID": "1234", "CustomerName": "KUMAR", "BranchName": "HARBOUR", "SchemeName": "GOLD", "MobileNumber": "123456789", "DedupeDetails": [ { "CustomerType": "PRIMARY", "CustomerName": "KUMAR", "DedupeFound" : "NO" }, { "CustomerType": "SECONDARY", "CustomerName": "SEAN", "DedupeFound" : "YES" } ] }, { "ID": "5678", "CustomerName": "MARK", "BranchName": "CANTONMENT", "SchemeName": "DIAMOND", "MobileNumber": "123456789", "DedupeDetails": [ { "CustomerType": "PRIMARY", "CustomerName": "MARK", "DedupeFound" : "NO" }, { "CustomerType": "SECONDARY", "CustomerName": "STEVE", "DedupeFound" : "YES" } ] } ]
现有代码问题
已经在Apache Camel中编写Java代码,成功将JSON字符串映射为对象列表,但不知道如何实现分组逻辑得到上述输出。现有代码如下:
package com.mycompany.Login; import java.util.List; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.sql.Timestamp; import java.io.File; import java.io.PrintWriter; import java.sql.Time; import com.mycompany.Login.*; import org.apache.camel.Exchange; import org.apache.camel.Processor; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.mycompany.Dedupe.DedupeRoot.DedupeRes; public class LoginMapping implements Processor{ public void process(Exchange ex)throws Exception{ try { String responseString = {Input mentioned in post}; ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); List<DedupeRes> dedupe = Arrays.asList(mapper.readValue(responseString, DedupeRes[].class)); int total = dedupe.size(); if (total > 0) { for (int i = 0; i < total; i++) { } } ex.getIn().setBody(responseString); } catch(Exception e) { ex.getIn().setHeader("ExpMsg", "Undefined"); throw e; } } }
实现方案
第一步:新增输出对应的实体类
首先创建两个新类,分别对应输出的外层结构和DedupeDetails的结构:
// 去重详情实体类 public class DedupeDetail { private String CustomerType; private String CustomerName; private String DedupeFound; // 补全getter、setter、无参构造方法 } // 输出结果外层实体类 public class DedupeOutput { private String ID; private String CustomerName; private String BranchName; private String SchemeName; private String MobileNumber; private List<DedupeDetail> DedupeDetails; // 补全getter、setter、无参构造方法 }
第二步:修改Processor的处理逻辑
替换process方法内的遍历部分,实现分组转换:
public void process(Exchange ex)throws Exception{ try { String responseString = ex.getIn().getBody(String.class); // 从Camel交换体取输入JSON,不要硬编码 ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); List<DedupeRes> dedupeList = Arrays.asList(mapper.readValue(responseString, DedupeRes[].class)); // 1. 按ID分组 HashMap<String, List<DedupeRes>> idGroupMap = new HashMap<>(); for (DedupeRes res : dedupeList) { idGroupMap.computeIfAbsent(res.getID(), k -> new ArrayList<>()).add(res); } // 2. 处理每个分组生成输出 List<DedupeOutput> outputList = new ArrayList<>(); for (String id : idGroupMap.keySet()) { List<DedupeRes> groupItems = idGroupMap.get(id); DedupeOutput output = new DedupeOutput(); List<DedupeDetail> details = new ArrayList<>(); for (DedupeRes item : groupItems) { // 填充去重详情 DedupeDetail detail = new DedupeDetail(); detail.setCustomerType(item.getCustomerType()); detail.setCustomerName(item.getCustomerName()); detail.setDedupeFound(item.getDedupeFound()); details.add(detail); // 找到主客户填充外层字段 if ("PRIMARY".equals(item.getCustomerType())) { output.setID(item.getID()); output.setCustomerName(item.getCustomerName()); output.setBranchName(item.getBranchName()); output.setSchemeName(item.getSchemeName()); output.setMobileNumber(item.getMobileNumber()); } } output.setDedupeDetails(details); outputList.add(output); } // 把输出列表转成JSON字符串放回交换体 String outputJson = mapper.writeValueAsString(outputList); ex.getIn().setBody(outputJson); } catch(Exception e) { ex.getIn().setHeader("ExpMsg", "Undefined"); throw e; } }
注意事项
- 确保你的
DedupeRes实体类已经包含所有输入字段对应的getter方法,否则取值会报错 - 如果你的Java版本支持Stream API,也可以用
Collectors.groupingBy替代HashMap手动分组,代码会更简洁 - 你提供的期望输出示例里部分字段末尾漏了逗号,实际转换时Jackson会自动处理格式问题
内容的提问来源于stack exchange,提问作者Chennai Cheetah
相关产品推荐
相关产品推荐

