使用Node.js将对象写入文件

111

我已经在StackOverflow/谷歌上搜索了很久,但是似乎无法解决。

我正在爬取某个URL页面的社交媒体链接,并且该函数返回一个包含URL列表的对象。

当我尝试将这些数据写入不同的文件时,它会输出到文件中显示为[object Object],而不是预期的:[ 'https://twitter.com/#!/101Cookbooks', 'http://www.facebook.com/101cookbooks'],就像在使用console.log()时看到的那样。

这是我的一次尝试,用Node读取和写入文件,尝试读取每一行(即URL),然后通过函数调用request(line, gotHTML)输入:

fs.readFileSync('./urls.txt').toString().split('\n').forEach(function (line){
    console.log(line); 
    var obj = request(line, gotHTML); 
    console.log(obj); 
    fs.writeFileSync('./data.json', obj , 'utf-8'); 
});   

供参考 -- gotHTML 函数:

function gotHTML(err, resp, html){ 
    var social_ids = []; 

    if(err){
        return console.log(err); 
    } else if (resp.statusCode === 200){ 
        var parsedHTML = $.load(html); 

        parsedHTML('a').map(function(i, link){
            var href = $(link).attr('href');
            for(var i=0; i<socialurls.length; i++){
                if(socialurls[i].test(href) && social_ids.indexOf(href) < 0 ) {
                    social_ids.push(href); 
                }; 
            }; 
        })
    };

    return social_ids;
};

3
[object Object] 是一个对象的 toString,如果想要该对象的表示,请使用 JSON.stringify - elclanrs
2
小心使用 JSON.stringify。对于数组,它是安全的,但是当对象存在循环引用时,它会失败(参见此主题)。util 模块可以处理循环引用。 - Joseph Yaduvanshi
7个回答

127

在deb2fast说的基础上,我也会传入一些额外的参数给JSON.stringify(),以便使其格式更加清晰易读:

fs.writeFileSync('./data.json', JSON.stringify(obj, null, 2) , 'utf-8');
第二个参数是一个可选的替换函数,在这种情况下您不需要它,因此 null 可以使用。第三个参数是用于缩进的空格数。2 和 4 似乎是流行选择。

1
它将会导致循环依赖问题。双向依赖关系无法转换为JSON。 - Ozan Ertürk
文本文件末尾缺少换行符。有什么办法可以修复这个问题吗? - friederbluemle
2
@friederbluemle - 你可以在 stringify() 调用中添加 + '\n' 来添加换行符。 - Guy
1
这个对我来说效果最好,因为使用被接受的答案给了我错误的结果。 - Anshuman Kumar

85

obj是您的示例中的数组。

fs.writeFileSync(filename, data, [options])要求数据参数为StringBuffer请参见文档

尝试以字符串格式编写数组:

// writes 'https://twitter.com/#!/101Cookbooks', 'http://www.facebook.com/101cookbooks'
fs.writeFileSync('./data.json', obj.join(',') , 'utf-8'); 
或者:
// writes ['https://twitter.com/#!/101Cookbooks', 'http://www.facebook.com/101cookbooks']
var util = require('util');
fs.writeFileSync('./data.json', util.inspect(obj) , 'utf-8');

编辑:您在示例中看到数组的原因是因为Node的console.log实现不仅调用toString,还调用了util.format请参见 console.js 源代码


9
如果您的对象包含大型数组,则此方法将无法正常工作,因为inspect方法将输出类似于“45000 more...]"的内容。 - Coxer

23

如果你得到了 [object object] ,那么使用 JSON.stringify

fs.writeFile('./data.json', JSON.stringify(obj) , 'utf-8');

这对我起作用了。


12

根据我的经验,JSON.stringify比util.inspect要稍微快一些。 我需要将一个包含92k行数据的DB2查询结果保存为json文件,使用util.inspect转换的时间太长了,所以我进行了以下测试,使用这两种方法将相同的1000条记录对象写入文件。

  1. JSON.stringify

  2. fs.writeFile('./data.json', JSON.stringify(obj, null, 2));
    

时间:3:57(3分钟57秒)

结果格式:

[
  {
    "PROB": "00001",
    "BO": "AXZ",
    "CNTRY": "649"
   },
  ...
]
  1. util.inspect

    var util = require('util');
    fs.writeFile('./data.json', util.inspect(obj, false, 2, false));
    

时间:4:12(4分12秒)

结果格式:

[ { PROB: '00001',
    BO: 'AXZ',
    CNTRY: '649' },
    ...
]

4

您可以尝试执行JSON.stringify(obj);

就像这样:

var stringify = JSON.stringify(obj);
fs.writeFileSync('./data.json', stringify, 'utf-8'); 

2

如果有人偶然看到这个问题,我使用Node中的fs-extra库,并像下面这样将JavaScript对象写入文件:

Original Answer翻译成"最初的回答"

const fse = require('fs-extra');
fse.outputJsonSync('path/to/output/file.json', objectToWriteToFile); 

0

关于@Jim Schubert@deb2fast的回答:

如果要能够写入大于~100 MB的大型objects,您需要使用下面所示的 for...of,并按照您的要求进行匹配。

const fsPromises = require('fs').promises;

const sampleData = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};

const writeToFile = async () => {
  for (const dataObject of Object.keys(sampleData)) {
      console.log(sampleData[dataObject]);
      await fsPromises.appendFile( "out.json" , dataObject +": "+ JSON.stringify(sampleData[dataObject]));
  }
}

writeToFile();

请参考https://dev59.com/FLvoa4cB1Zd3GeqP1VEm#67699911获取有关node.js限制的完整参考资料。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接