Java实现从Excel提取数据生成动态嵌套JSON的技术需求
解决Java Excel转嵌套JSON的问题
核心问题诊断
你的现有代码是把Excel首行作为键、后续行直接转成扁平键值对,这种方式只会生成行级扁平JSON数组,完全没处理数据的层级关联,自然得不到嵌套结构。要生成动态计算的复杂嵌套JSON,必须先分析Excel数据的层级依赖关系,再按层级聚合数据。
分步解决方案
1. 先定义Excel数据的层级规则
假设你的Excel列结构是(请替换成你实际的列):顶级分类, 二级分类, 项目名称, 项目值
层级逻辑为:顶级分类 -> 二级分类 -> 项目列表
2. 读取Excel并封装数据
用Apache POI读取Excel,把每行数据封装成实体类,方便后续处理:
import org.apache.poi.ss.usermodel.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ExcelRow { private String topCategory; private String subCategory; private String itemName; private String itemValue; // 构造器、getter、setter省略 } // 读取Excel的方法 public List<ExcelRow> readExcel(String filePath) throws Exception { List<ExcelRow> rows = new ArrayList<>(); Workbook workbook = WorkbookFactory.create(new java.io.File(filePath)); Sheet sheet = workbook.getSheetAt(0); Iterator<Row> rowIterator = sheet.iterator(); rowIterator.next(); // 跳过首行表头 while (rowIterator.hasNext()) { Row row = rowIterator.next(); ExcelRow excelRow = new ExcelRow(); excelRow.setTopCategory(row.getCell(0).getStringCellValue()); excelRow.setSubCategory(row.getCell(1).getStringCellValue()); excelRow.setItemName(row.getCell(2).getStringCellValue()); excelRow.setItemValue(row.getCell(3).getStringCellValue()); rows.add(excelRow); } workbook.close(); return rows; }
3. 按层级聚合生成嵌套结构
用HashMap分组,结合Jackson构建嵌套JSON:
import com.fasterxml.jackson.databind.ObjectMapper; import java.util.*; import java.util.stream.Collectors; public class NestedJsonGenerator { public static void main(String[] args) throws Exception { List<ExcelRow> rows = readExcel("your-excel-file.xlsx"); // 第一步:按顶级分类分组 Map<String, List<ExcelRow>> topCategoryGroups = rows.stream() .collect(Collectors.groupingBy(ExcelRow::getTopCategory)); // 第二步:构建嵌套结构 List<Map<String, Object>> nestedResult = new ArrayList<>(); for (Map.Entry<String, List<ExcelRow>> topEntry : topCategoryGroups.entrySet()) { Map<String, Object> topCategoryMap = new HashMap<>(); topCategoryMap.put("topCategory", topEntry.getKey()); // 按二级分类分组 Map<String, List<ExcelRow>> subCategoryGroups = topEntry.getValue().stream() .collect(Collectors.groupingBy(ExcelRow::getSubCategory)); List<Map<String, Object>> subCategories = new ArrayList<>(); for (Map.Entry<String, List<ExcelRow>> subEntry : subCategoryGroups.entrySet()) { Map<String, Object> subCategoryMap = new HashMap<>(); subCategoryMap.put("subCategory", subEntry.getKey()); // 生成项目列表 List<Map<String, String>> items = subEntry.getValue().stream() .map(row -> { Map<String, String> item = new HashMap<>(); item.put("name", row.getItemName()); item.put("value", row.getItemValue()); return item; }) .collect(Collectors.toList()); subCategoryMap.put("items", items); subCategories.add(subCategoryMap); } topCategoryMap.put("subCategories", subCategories); nestedResult.add(topCategoryMap); } // 转成格式化后的JSON字符串 ObjectMapper objectMapper = new ObjectMapper(); String nestedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(nestedResult); System.out.println(nestedJson); } }
4. 适配你的指定嵌套结构
如果你的目标JSON结构有特殊要求(比如某层级是对象而非数组、有动态计算字段),只需要调整分组逻辑和Map的构建即可:
- 若某层级是唯一对象(而非多个子项),把
List<Map>改成单个Map - 动态计算字段可以在构建Map时直接添加,比如
subCategoryMap.put("totalValue", calculateTotal(subEntry.getValue()))
依赖说明
确保你的pom.xml(Maven)里引入以下依赖:
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.5</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> </dependencies>
内容的提问来源于stack exchange,提问作者Shyam Sundar V
相关产品推荐
相关产品推荐

