NodeJS中如何在for循环内将对象写入数组格式的JSON文件?
解决JSON数组文件的追加写入问题
场景与问题
在for循环中执行axios POST请求,需将请求相关对象存入数组格式的JSON文件,且后续运行时要追加新对象、不覆盖原有内容。当前代码生成的JSON格式不符合标准,缺少数组方括号和对象间的分隔逗号。
当前代码
var arrayFile = fs.createWriteStream("arrayFile.json", { flags: "a" }) for (var x = 0; x < 2; x++) { await axios .post(destinationURL, config) .then(res => { const obj = { id: x, user: config.user, password: config.password, } arrayFile.write(JSON.stringify(obj, null, 2), "utf-8") }) }
当前错误输出格式
{ "id": 0, "user": "testUser1", "password": "ThisIsPassword" }{ "id": 1, "user": "testUser2", "password": "ThisIsPassword" }
期望输出格式
[ { "id": 0, "user": "testUser1", "password": "ThisIsPassword" }, { "id": 1, "user": "testUser2", "password": "ThisIsPassword" } ]
解决方案
方案1:先收集数据再统一写入(小数据场景)
逻辑简单,先将所有请求结果存入内存数组,再合并到现有文件的数组中,适合数据量不大的情况。
const fs = require('fs').promises; const axios = require('axios'); async function saveData() { const newData = []; // 批量执行请求,收集数据 for (let x = 0; x < 2; x++) { await axios.post(destinationURL, config); newData.push({ id: x, user: config.user, password: config.password }); } let existingArray = []; try { // 读取现有文件内容 const fileContent = await fs.readFile('arrayFile.json', 'utf-8'); existingArray = JSON.parse(fileContent); } catch (err) { // 文件不存在时初始化空数组 if (err.code !== 'ENOENT') throw err; } // 合并新旧数据并写入 const finalData = [...existingArray, ...newData]; await fs.writeFile('arrayFile.json', JSON.stringify(finalData, null, 2), 'utf-8'); } saveData();
方案2:流式追加写入(大数据场景)
避免一次性加载大量数据到内存,通过操作文件指针实现流式追加,适合数据量较大的场景。
const fs = require('fs'); const fsPromises = require('fs').promises; const axios = require('axios'); async function appendToJsonArray() { const filePath = 'arrayFile.json'; let isFirstWrite = false; // 检查文件状态,判断是否为首次写入 try { await fsPromises.access(filePath); const stats = await fsPromises.stat(filePath); if (stats.size === 0) { isFirstWrite = true; } else { // 定位到文件末尾,移除闭合的] const fd = await fsPromises.open(filePath, 'r+'); await fd.seek(stats.size - 1); const buf = Buffer.alloc(1); await fd.read(buf, 0, 1, stats.size - 1); await fd.close(); if (buf.toString() !== ']') { throw new Error('JSON文件格式异常,不是有效的数组'); } await fsPromises.truncate(filePath, stats.size - 1); } } catch (err) { if (err.code === 'ENOENT') isFirstWrite = true; else throw err; } const stream = fs.createWriteStream(filePath, { flags: 'a' }); // 写入数组开头或分隔符 isFirstWrite ? stream.write('[', 'utf-8') : stream.write(',', 'utf-8'); // 循环执行请求并写入对象 for (let x = 0; x < 2; x++) { await axios.post(destinationURL, config); const objStr = JSON.stringify({ id: x, user: config.user, password: config.password }, null, 2); // 保持格式美观,添加换行和缩进 if ((isFirstWrite && x > 0) || (!isFirstWrite && x === 0)) { stream.write('\n ', 'utf-8'); } else if (x > 0) { stream.write(',\n ', 'utf-8'); } stream.write(objStr, 'utf-8'); } // 写入数组闭合符 stream.write('\n]', 'utf-8'); stream.end(); } appendToJsonArray();
注意事项
- 方案1实现简单,易维护,但数据量过大时会占用较多内存。
- 方案2内存占用低,但需处理文件格式异常等边界情况,建议添加完善的错误捕获逻辑。
- 若请求可能失败,需添加回滚机制,避免破坏JSON文件格式。
内容的提问来源于stack exchange,提问作者InvisiblePotato
相关产品推荐
相关产品推荐

