使用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
相关产品推荐
相关产品推荐

