如何使用Node.js将JSON数组转换为CSV?

24

我想转换带有值数组的JSON。 response.json

{
"rows": [
[
  "New Visitor",
  "(not set)",
  "(not set)",      
  "0"
],
[
  "New Visitor",
  "(not set)",
  "(not set)",
  "mobile"      
],
[
  "New Visitor",
  "(not set)",
  "(not set)",
  "mobile"    
],
  [
    "New Visitor",
    "(not set)",
    "(not set)",
   "mobile",      
  ]
 ]
}

现在我想将这些数据转换为name.csv文件。

 "New Visitor","(not set)","(not set)","0"
 "New Visitor","(not set)","(not set)","mobile"        
 "New Visitor","(not set)","(not set)","mobile"    
 "New Visitor","(not set)","(not set)","mobile"
请使用Node.js给我提供建议。
5个回答

44

像这样自己做:

'use strict';

var fs = require('fs');

let myObj = {
  "rows": [
    [
      "New , Visitor",
      "(not set)",
      "(not set)",
      "0"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile",
    ]
  ]
}

// 1. One way - if you want the results to be in double quotes and you have comas inside

// choose another string to temporally replace commas if necessary
let stringToReplaceComas = '!!!!';

myObj.rows.map((singleRow) => {
  singleRow.map((value, index) => {
    singleRow[index] = value.replace(/,/g, stringToReplaceComas);
  })
})

let csv = `"${myObj.rows.join('"\n"').replace(/,/g, '","')}"`;
// // or like this
// let csv = `"${myObj.rows.join('"\n"').split(',').join('","')}"`;

csv = csv.replace(new RegExp(`${stringToReplaceComas}`, 'g'), ',');

// // 2. Another way - if you don't need the double quotes in the generated csv and you don't have comas in rows' values
// let csv = myObj.rows.join('\n')

fs.writeFile('name.csv', csv, 'utf8', function(err) {
  if (err) {
    console.log('Some error occured - file either not saved or corrupted file saved.');
  } else {
    console.log('It\'s saved!');
  }
});

使用库

例如:https://github.com/mrodrig/json-2-csvhttps://github.com/wdavidw/node-csvhttps://github.com/wdavidw/node-csv-stringify

以下是使用json-2-csv(https://github.com/mrodrig/json-2-csv)的示例:

'use strict';

const converter = require('json-2-csv');

let myObj = {
  "rows": [
    {
      value1: "New Visitor",
      value2: "(not set)",
      value3: "(not set)",
      value4: "0"
    },
    {
      value1: "New Visitor",
      value2: "(not set)",
      value3: "(not set)",
      value4: "mobile"
    },
    {
      value1: "New Visitor",
      value2: "(not set)",
      value3: "(not set)",
      value4: "mobile"
    },
    {
      value1: "New Visitor",
      value2: "(not set)",
      value3: "(not set)",
      value4: "mobile",
    }
  ]
}

let json2csvCallback = function (err, csv) {
    if (err) throw err;
    fs.writeFile('name.csv', csv, 'utf8', function(err) {
      if (err) {
        console.log('Some error occured - file either not saved or corrupted file saved.');
      } else {
        console.log('It\'s saved!');
      }
    });
};

converter.json2csv(myObj.rows, json2csvCallback, {
  prependHeader: false      // removes the generated header of "value1,value2,value3,value4" (in case you don't want it)
});

一个使用csv-stringify的例子(https://github.com/wdavidw/node-csv-stringify

'use strict';

var stringify = require('csv-stringify');
var fs = require('fs');

let myObj = {
  "rows": [
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "0"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile",
    ]
  ]
}

stringify(myObj.rows, function(err, output) {
  fs.writeFile('name.csv', output, 'utf8', function(err) {
    if (err) {
      console.log('Some error occured - file either not saved or corrupted file saved.');
    } else {
      console.log('It\'s saved!');
    }
  });
});

1
感谢您的回答!它真的帮助了我。您能否使用Node-csv库编写相同的代码,因为我想读取约1GB的数据。 - arjun kori
1
我已经编辑了上面的例子,你可以测试一下,告诉我是否可行。 - Relu Mesaros
1
在使用正则表达式生成CSV文件时要小心。JSON值可能包含逗号作为值的一部分,这会引起问题。例如:[ "Visitor, New", "(not set)", …] 会变成 "New"," Visitor","(not set)", …。不过,我确实喜欢你在父数组上使用单个.join的方法,并且我已经更新了我的答案,以引用你使用这种技术的方式。 - gfullam
1
该程序库“csv-stringify”涵盖了这种情况(“访客,新”)。 - Relu Mesaros
2
我已经编辑了我的代码,现在逗号的情况也被覆盖了,感谢 @gfullam 的简要说明,你让我意识到了我目前正在工作的项目中存在一个 bug... - Relu Mesaros
显示剩余2条评论

14

三个简单步骤:读取、转换和写入

第一步:读取。

如果您需要从文件中读取JSON(根据您在帖子中包含的文件名response.json),则需要使用Node.js FileSystem API

const fs = require('fs');                          // Require Node.js FileSystem API.
const JSONFile = fs.readFileSync('response.json'); // Read the file synchronously.
< p >注意:如果您愿意,可以使用fs.readFile()异步读取文件,并在回调函数中执行转换。

步骤2:转换。

无论是从本地文件还是从服务器获取JSON数据,都需要首先使用JSON.parse方法将其解析为普通的JavaScript对象:

const JSONasPOJO = JSON.parse(JSONFile); // Parse JSON into POJO.

请见下文的编辑

/* THIS IS UNNECESSARY FOR "COMMA" SEPARATED VALUES
const CSVString = JSONasPOJO
    .rows                    // Get `rows`, which is an array.
    .map(                    // Map returns a new array.
        row => row.join(',') // Each child array becomes a comma-separated string.  
     )                    
    .join('\n');             // Parent array becomes a newline-separated string...
                             // ...of comma-separated strings.
                             // It is now a single CSV string!
*/

编辑:

虽然前面的代码能够正常工作,但在子数组上使用 .map.join 是不必要的。如@Relu演示,只需在父数组上使用单个.join即可,因为JavaScript会自动将子数组转换为逗号分隔的字符串,这是默认行为,因为.join必须返回字符串并且不能包含任何子数组。

如果你想用其他符号连接子数组,可以使用上述模式。

否则:

var CSVString = JSONasPOJO.rows.join('\n'); // Array becomes a newline-separated...
                                            // ...string of comma-separated strings.
                                            // It is now a single CSV string!

在这里,我们可以看到转换的实际效果:

const JSONasPOJO = {
  "rows": [
    [
      "New Visitor",
      "(not set)",
      "(not set)",      
      "0"
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"      
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile"    
    ],
    [
      "New Visitor",
      "(not set)",
      "(not set)",
      "mobile" // NOTE: Here I removed a trailing comma,
               // ...which is invalid JSON!
    ]
  ]
}

const CSVString = JSONasPOJO.rows.join('\n');

console.log(CSVString);

步骤三:写入。

再次使用文件系统 API,将内容写入文件,并记录错误或成功信息:

fs.writeFile('name.csv', CSVString, err => {
    if (err) return console.log(err);
    console.log('FILE SUCCESSFULLY WRITTEN!\n');
});

注意:这里我使用回调来记录错误和成功信息,演示异步模式。如果你喜欢,你也可以使用fs.writeFileSync()同步写文件。

将其整合在一起

我喜欢在我的Node.js脚本中添加大量的console.log()消息。

const fs = require('fs');

const inFilename  = 'response.json',
      outFilename = 'name.csv';

console.log(`Preparing to read from ${inFilename} …`);

const JSONContents = fs.readFileSync(inFilename);

console.log(`READ:\n${JSONContents}`);
console.log('Preparing to parse as JSON …');

const JSONasPOJO = JSON.parse(JSONContents);

console.log(`PARSED:\n${JSONasPOJO}`);
console.log('Preparing to convert into CSV …');

const CSVString = JSONasPOJO.rows.join('\n');

console.log(`CONVERTED:\n${CSVString}`);
console.log(`Preparing to write to ${outFilename} …`);

fs.writeFile(outFilename, CSVString, err => {
    if (err) return console.error(err);
    console.log('FILE SUCCESSFULLY WRITTEN!');
});

4

我不知道你们怎么看,但我喜欢小巧且无需大量配置即可正常工作的软件包。尝试使用jsonexport,我认为它是最好的模块之一,能很好地处理对象、数组等,并且速度快!

安装

npm i --save jsonexport

使用方法

const jsonexport = require('jsonexport');
const fs = require('fs');

jsonexport([{
  value1: "New Visitor",
  value2: "(not set)",
  value3: "(not set)",
  value4: "0"
},
{
  value1: "New Visitor",
  value2: "(not set)",
  value3: "(not set)",
  value4: "mobile"
},
{
  value1: "New Visitor",
  value2: "(not set)",
  value3: "(not set)",
  value4: "mobile"
},
{
  value1: "New Visitor",
  value2: "(not set)",
  value3: "(not set)",
  value4: "mobile",
}], function(err, csv) {
  if (err) return console.error(err);
  fs.writeFile('output.csv', csv, function(err) {
    if (err) return console.error(err);
    console.log('output.csv saved');
  });
});

https://github.com/kauegimenes/jsonexport


5
请注意,这个库是你自己的库。不披露这一点违反了网站的行为准则。 - Isaac
好的库!感谢帮助。 - Chirag Gupta

1

0

我想分享一种从JSON数组构建CSV字符串的最简单方法:

const data = [
  { a: 1, b: new Date(), c: 'a text' },
  {
    a: 1, b: new Date(), c: `string
  with
  return
  carrier
  and emoji 
  `
  }
]

const header = Object.keys(data[0]).map(_ => JSON.stringify(_)).join(';') + '\n'
const outData = data.reduce((acc, row) => {
  return acc + Object.values(row).map(_ => JSON.stringify(_)).join(';') + '\n'
}, header)

console.log(outData)

将打印此字符串:

"a";"b";"c"
1;"2020-03-25T08:49:04.280Z";"a text"
1;"2020-03-25T08:49:04.280Z";"string\n  with\n  return\n  carrier\n  and emoji \n  "

谢谢,Manuel。我一个一个尝试了这个问题的所有答案,只有你的有效。也许我们可以把它转换成一个库 :) - undefined

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