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

Posted

技术标签:

【中文标题】如何使用 Node.js 将 JSON 数组转换为 CSV?【英文标题】:How to convert JSON array to CSV using Node.js? 【发布时间】:2016-11-09 16:51:01 【问题描述】:

我想转换具有值数组的 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 的建议。

【问题讨论】:

【参考方案1】:

像这样自己做:

'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-csv、https://github.com/wdavidw/node-csv、https://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!');
    
  );
);

【讨论】:

感谢您的回答!它真的对我有帮助。您可以使用 node-csv 库编写相同的代码,因为我想读取大约 1GB 的数据。 我已经编辑了上面的例子,你可以测试一下,告诉我它是否有效 小心使用正则表达式生成 CSV 文件。 JSON 值可能包含逗号作为值的一部分,这会导致麻烦。例如:[ "Visitor, New", "(not set)", …] 将变为 "New"," Visitor","(not set)", …。但是,我确实喜欢您在父数组上使用单个 .join,并且我已经更新了我的答案以参考您对这种技术的使用。 库“csv-stringify”涵盖了这种情况(“Visitor, New”) 我已经编辑了我的代码,现在涵盖了昏迷的情况,感谢简短的@gfullam,你让我意识到我目前正在处理的项目中有一个错误...... 【参考方案2】:

三个简单的步骤:阅读。转变。写。

第 1 步:阅读。

如果您需要从文件中读取 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.

注意:如果您愿意,可以使用fs.readFile() 异步读取文件并在回调函数中执行转换。

第 2 步:转换。

无论您是从本地文件读取 JSON 还是从服务器获取 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 demonstrates 一样,父数组上的单个.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);

第 3 步:写作。

再次使用 FileSystem 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!');
);

【讨论】:

【参考方案3】:

我不了解你们,但我喜欢无需大量额外配置即可按预期工作的小包,尝试使用 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

【讨论】:

你可能要注意这个库是你自己的库。不披露这一点违反网站行为【参考方案4】:

在尝试使用该库几个小时后,我最终编写了自己的库。 https://github.com/KhanhPham2411/simple-node-csv

import  SimpleNodeCsv  from './simple-node-csv';

SimpleNodeCsv.obj2csv(a: 1, b:2, ",");

// output
// "a","b"
// 1,2

【讨论】:

【参考方案5】:

我想分享从 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  "

【讨论】:

以上是关于如何使用 Node.js 将 JSON 数组转换为 CSV?的主要内容,如果未能解决你的问题,请参考以下文章

在 Node.js 中响应 JSON 对象(将对象/数组转换为 JSON 字符串)

如何使用 Node.js 将 CSV 文件转换为 JSON 脚本?

如何将 MongooseMap 转换为 JSON 对象以将其从 Node js 发送到 React?

将rowdatapacket转换为数组,如何将mysql node.js api rowdatapacket转换为数组,将字符串转换为数组

如何将mysql的数据行转换为javascript数组? Node.js 应用程序

将 node.js 缓冲区转换为字符串,然后转换为 JSON