You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:18:16