将Excel数据保存为JSON文件时Postman请求触发空指针异常排查
Excel转JSON空指针异常排查与修正
一、空指针异常的触发原因
你的代码中存在多处未做null校验的场景,这是触发NPE的核心原因:
- 表头行或数据行不存在:如果Excel的第一行(表头)为空,
workSheet.getRow(0)会返回null,后续调用header.getCell(j)直接抛出空指针;同理,数据行中若存在空行,workSheet.getRow(i)返回null后,调用row.getPhysicalNumberOfCells()也会报错。 - 单元格为空:Excel中某列无内容时,POI会返回null单元格,直接调用
cell.toString()会触发空指针。 - 硬编码路径风险:
writeData2JsonFile方法中硬写磁盘路径,若路径不存在或无写入权限,虽不会直接触发NPE,但会导致文件写入失败,同时在不同环境下兼容性极差。
二、修正后的参考代码
以下是加入null校验、资源自动管理、路径优化的完整代码:
import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.json.simple.JSONObject; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.google.gson.Gson; @RestController public class ExcelController { @PostMapping("/excel") public String getExcel(@RequestParam("file") MultipartFile file) { try { excel2Json(file); return "Success"; } catch (Exception e) { e.printStackTrace(); return "Failed: " + e.getMessage(); } } public void excel2Json(MultipartFile file) throws IOException { // 使用try-with-resources自动关闭工作簿 try (XSSFWorkbook workBook = new XSSFWorkbook(file.getInputStream())) { XSSFSheet workSheet = workBook.getSheetAt(0); if (workSheet == null) { throw new IllegalArgumentException("Excel中无有效工作表"); } List<JSONObject> dataList = new ArrayList<>(); Row header = workSheet.getRow(0); if (header == null) { throw new IllegalArgumentException("Excel表头行不能为空"); } int lastRowNum = workSheet.getLastRowNum(); for (int i = 1; i <= lastRowNum; i++) { Row row = workSheet.getRow(i); if (row == null) { continue; // 跳过空行 } JSONObject rowJsonObject = new JSONObject(); int lastCellNum = header.getLastCellNum(); for (int j = 0; j < lastCellNum; j++) { Cell headerCell = header.getCell(j); Cell dataCell = row.getCell(j); // 处理表头单元格为空的情况 String columnName = headerCell != null ? getCellValue(headerCell) : "col_" + j; // 处理数据单元格为空的情况 String columnValue = dataCell != null ? getCellValue(dataCell) : ""; rowJsonObject.put(columnName, columnValue); } dataList.add(rowJsonObject); } writeData2JsonFile(dataList); } } // 统一处理不同类型单元格的取值逻辑 private String getCellValue(Cell cell) { switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: return String.valueOf(cell.getNumericCellValue()); case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); case FORMULA: return cell.getCellFormula(); default: return ""; } } public void writeData2JsonFile(List<JSONObject> dataList) throws IOException { // 推荐使用项目根目录下的输出路径,或通过配置文件注入路径 String outputPath = "data.json"; // 若要写入resource目录,注意运行时resource目录可能被打包,建议写入外部指定路径 // String outputPath = "src/main/resources/data.json"; Gson gson = new Gson(); // try-with-resources自动关闭文件写入流 try (FileWriter fileWriter = new FileWriter(outputPath)) { fileWriter.write(gson.toJson(dataList)); } } }
三、额外优化建议
- 单元格类型处理:原代码直接调用
toString()会导致日期、数字等类型格式异常,新增的getCellValue方法统一处理不同单元格类型的取值逻辑。 - 资源自动管理:使用try-with-resources语法自动关闭
XSSFWorkbook和FileWriter,避免资源泄漏。 - 错误反馈:在接口层捕获异常并返回错误信息,便于排查问题。
- 路径配置:避免硬编码路径,可通过
@Value注解从配置文件中读取输出路径,提升代码兼容性。
内容的提问来源于stack exchange,提问作者Apratim Dutta Choudhury
相关产品推荐
相关产品推荐

