【问题标题】:How to convert JSON array to CSV using Node.js?如何使用 Node.js 将 JSON 数组转换为 CSV?
【发布时间】: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 的建议。

【问题讨论】:

    标签: json node.js csv express


    【解决方案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-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!');
        }
      });
    });
    

    【讨论】:

    • 感谢您的回答!它真的对我有帮助。您可以使用 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  "
        

        【讨论】:

          猜你喜欢
          • 2015-03-05
          • 1970-01-01
          • 2022-11-17
          • 1970-01-01
          • 2017-09-07
          • 2013-05-25
          • 2016-09-02
          • 2018-05-23
          相关资源
          最近更新 更多