Java如何拆分嵌套列表的子元素,生成保留父字段的多条独立对象列表?
实现方案
核心逻辑是遍历所有原始员工对象,再遍历每个员工的地址列表,为每个地址生成一个独立的员工副本,副本保留原员工除地址外的所有字段,地址列表仅保留当前遍历到的单个地址。
方式1:基于实体类转换(Java 8+ 流实现)
首先定义对应实体类(示例用Lombok简化getter/setter、构造方法,无Lombok自行补充对应方法即可):
import lombok.AllArgsConstructor; import lombok.Data; import java.util.List; @Data @AllArgsConstructor public class Address { private String line1; private String line2; private String town; private String city; private String zipCode; // 可根据实际JSON字段调整属性名,比如补充state字段 } @Data @AllArgsConstructor public class Employee { private Integer id; private String name; private String lname; private List<Address> address; }
核心转换方法:
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class EmployeeSplitUtil { public static List<Employee> splitByAddress(List<Employee> originalEmployees) { return originalEmployees.stream() .flatMap(emp -> emp.getAddress().stream() .map(singleAddr -> { List<Address> singleAddrList = new ArrayList<>(); // 若需深拷贝避免修改影响原数据,可替换为 new Address(xxx) 复制所有属性 singleAddrList.add(singleAddr); // 复制原员工所有非地址字段 return new Employee(emp.getId(), emp.getName(), emp.getLname(), singleAddrList); }) ) .collect(Collectors.toList()); } public static void main(String[] args) { // 测试用例 List<Address> addresses = new ArrayList<>(); addresses.add(new Address("Address 1 Line 1", "Address 1 Line 2", "Address 1 town", "Address 1 city", "12345")); addresses.add(new Address("Address 2 Line 1", "Address 2 Line 2", "Address 2 town", "Address 2 city", "22222")); addresses.add(new Address("Address 3 Line 1", "Address 3 Line 2", "Address 3 town", "Address 3 city", "33333")); Employee employee1 = new Employee(100, "adnan", "ahmed", addresses); List<Employee> originList = new ArrayList<>(); originList.add(employee1); // 执行转换 List<Employee> result = splitByAddress(originList); // 用Jackson/Gson序列化result即可得到目标JSON } }
方式2:直接操作JSON节点(Jackson为例)
如果不需要转实体类,可直接操作JSON结构完成转换:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; public class JsonSplitUtil { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 假设originJson是你的原始JSON字符串 String originJson = "{\"employee\":[{\"name\":\"adnan\",\"lname\":\"ahmed\",\"address\":[{\"state\":\"a\",\"city\":\"b\"},{\"state\":\"c\",\"city\":\"d\"}]}]}"; JsonNode root = mapper.readTree(originJson); ArrayNode originEmpArray = (ArrayNode) root.get("employee"); ArrayNode resultEmpArray = mapper.createArrayNode(); for (JsonNode empNode : originEmpArray) { ArrayNode addrArray = (ArrayNode) empNode.get("address"); for (JsonNode addr : addrArray) { // 复制原员工节点所有属性 ObjectNode newEmpNode = empNode.deepCopy(); // 替换为仅含单个地址的数组 ArrayNode singleAddrArray = mapper.createArrayNode(); singleAddrArray.add(addr); newEmpNode.set("address", singleAddrArray); resultEmpArray.add(newEmpNode); } } // 输出结果 ((ObjectNode) root).set("employee", resultEmpArray); System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root)); } }
注意事项
- 若实体类有更多自定义字段,构造新员工对象时需全部复制,避免字段丢失
- 若需对地址做深拷贝,可自行复制Address的所有属性生成新对象,避免后续修改影响原始数据
内容的提问来源于stack exchange,提问作者adnan ahmed
相关产品推荐
相关产品推荐

