Node.js堆内存溢出求助:大JSON对象写入失败
解决Node.js大对象JSON序列化内存溢出问题
你的问题根源很明确:JSON.stringify(o)会一次性把整个百万级对象转换成一个超大字符串,这个字符串完全占用堆内存——哪怕后面用流式写入也已经晚了,内存早就被巨量的字符串占满,自然触发堆内存不足的致命错误。
下面给你两个实用的解决方案:
方案一:使用流式JSON序列化库(推荐)
第三方库stream-json专门解决这类问题,它可以边遍历对象边输出JSON内容,不会把完整的JSON字符串加载到内存中,内存占用极低。
步骤:
- 先安装依赖:
npm install stream-json
- 修改你的保存函数:
const fs = require('fs'); const { stringify } = require('stream-json/Stringer'); function saveObjectAsJSON(o, filename) { const writeStream = fs.createWriteStream(filename); // 将对象序列化流直接管道到文件写入流 stringify(o).pipe(writeStream); }
这个方法不管你的大对象是数组还是嵌套结构,都能完美处理,底层会自动分块处理数据,完全避免内存溢出。
方案二:手动分块处理(无第三方依赖)
如果你的外层对象是包含百万条数据的数组,可以手动遍历数组,逐个序列化每个元素,再拼接成合法的JSON数组格式,这样每次内存中只保留单个元素的JSON字符串。
示例代码:
const fs = require('fs'); async function saveLargeArrayAsJSON(largeArray, filename) { const writeStream = fs.createWriteStream(filename); // 先写入JSON数组的开头 writeStream.write('['); for (let index = 0; index < largeArray.length; index++) { const item = largeArray[index]; const itemJson = JSON.stringify(item); // 除了第一个元素,前面要加逗号分隔符 if (index > 0) { writeStream.write(','); } // 写入当前元素的JSON writeStream.write(itemJson); // 每处理1000条就等待流排空,避免内部缓冲堆积 if (index % 1000 === 0) { await new Promise(resolve => writeStream.once('drain', resolve)); } } // 写入JSON数组的结尾 writeStream.write(']'); writeStream.end(); }
注意事项:
- 这个方法只适用于外层是数组的情况,如果是复杂嵌套对象,手动处理格式会非常繁琐,还是推荐方案一。
- 加入
drain事件的等待是为了防止写入流的内部缓冲溢出,保证写入过程稳定。
内容的提问来源于stack exchange,提问作者cbll
相关产品推荐
相关产品推荐

