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

使用Java将Excel转JSON导入MongoDB时出现异常

解决Excel转JSON导入MongoDB时的BasicBSONList can only work with numeric keys异常

问题根源

你遇到的java.lang.IllegalArgumentException: BasicBSONList can only work with numeric keys, not: [_id]异常,核心原因是JSON数组解析后的类型处理错误:

  • 当你用JSON.parse(inputJson)解析JSON数组字符串时,返回的对象是BasicBSONList(MongoDB对BSON数组的实现,本质是带数字索引的列表),而不是DBObject[]数组。
  • 强制将BasicBSONList转换为DBObject[]会导致类型不匹配,当MongoDB尝试给每个文档自动添加_id字段时,BasicBSONList只支持数字键,无法处理字符串类型的_id键,因此抛出异常。

解决方案:修正MongoDB插入逻辑

修改你的MongodbConn类中的解析和插入代码,正确处理BasicBSONList中的每个文档:

package company;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.util.JSON;
import com.mongodb.util.BasicBSONList;
import java.util.ArrayList;
import java.util.List;

public class MongodbConn {
    public static void main(String[] args) {
        MyFinalProject obj = new MyFinalProject();
        try {
            Mongo mongo = new Mongo("localhost", 27017);
            DB db = mongo.getDB("yourdb");
            DBCollection collection = db.getCollection("Test");
            String inputJson = obj.readExcel("C://Users//Prativa Mondal//Documents//Book1.xlsx", 0);
            System.out.println("jsonList: " + inputJson);

            // 修正:解析JSON数组为BasicBSONList,而非强制转换为DBObject[]
            BasicBSONList bsonList = (BasicBSONList) JSON.parse(inputJson);
            List<DBObject> dbObjects = new ArrayList<>();
            for (Object item : bsonList) {
                if (item instanceof DBObject) {
                    dbObjects.add((DBObject) item);
                }
            }

            // 批量插入文档
            collection.insert(dbObjects);

            // 验证插入结果
            DBCursor cursorDoc = collection.find();
            while (cursorDoc.hasNext()) {
                System.out.println(cursorDoc.next());
            }
            System.out.println("Done");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

额外优化:处理Excel数值类型(可选)

你输出的JSON中,ROLLNO.和AGE字段是带.0的字符串(比如"111.0"),这是因为Excel中这些单元格是数值类型,直接调用toString()会保留小数位。可以在MyFinalProject类中添加一个工具方法,根据单元格类型处理值:

package company;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.DateUtil;
import com.google.gson.Gson;
import java.io.File;
import java.util.*;

public class MyFinalProject {

    // 新增工具方法:根据单元格类型获取正确的字符串值
    private String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    double numericValue = cell.getNumericCellValue();
                    // 判断是否为整数,是则转为整数字符串
                    if (numericValue == Math.floor(numericValue)) {
                        return String.valueOf((long) numericValue);
                    }
                    return String.valueOf(numericValue);
                }
            case STRING:
                return cell.getStringCellValue().trim();
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    public String readExcel(String filePath, int sheetNumber) {
        String jsonCartList = null;
        try {
            File f = new File(filePath);
            Workbook wb = WorkbookFactory.create(f);
            Sheet mySheet = wb.getSheetAt(sheetNumber);
            int rowCount = 0;
            List<Map<String, String>> hmap = new ArrayList<>();
            List<String> keyList = new ArrayList<>();
            List<String> valueList = new ArrayList<>();

            for (Iterator<Row> rowIterator = mySheet.rowIterator(); rowIterator.hasNext(); ) {
                Row row = rowIterator.next();
                for (Iterator<Cell> cellIterator = row.cellIterator(); cellIterator.hasNext(); ) {
                    Cell cell = cellIterator.next();
                    if (rowCount == 0) {
                        keyList.add(getCellValue(cell));
                    } else {
                        valueList.add(getCellValue(cell));
                    }
                }
                rowCount += 1;
            }

            for (int vCount = 0; vCount < valueList.size(); vCount += keyList.size()) {
                Map<String, String> map = new HashMap<>();
                for (int kCount = 0; kCount < keyList.size(); kCount++) {
                    map.put(keyList.get(kCount), valueList.get(kCount + vCount));
                }
                hmap.add(map);
            }

            Gson gson = new Gson();
            jsonCartList = gson.toJson(hmap);
        } catch (Exception e) {
            System.out.println("Exception");
            e.printStackTrace();
        }
        return jsonCartList;
    }
}

优化后,ROLLNO.会变成"111",AGE变成"23",更符合业务预期。

内容的提问来源于stack exchange,提问作者Prativa Mondal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:28:52