【问题标题】:convert CSV lines into Javascript objects将 CSV 行转换为 Javascript 对象
【发布时间】:2015-04-17 02:31:35
【问题描述】:

我有一个简单的 csv 文件

people.csv:

fname, lname, uid, phone, address
John, Doe, 1, 444-555-6666, 34 dead rd
Jane, Doe, 2, 555-444-7777, 24 dead rd
Jimmy, James, 3, 111-222-3333, 60 alive way

我想要做的是获取 CSV 的每一行,将其转换为 JavaScript 对象,将它们存储到数组中,然后将数组转换为 JSON 对象。

server.js:

var http = require('http');
var url  = require('url');
var fs = require('fs');

var args = process.argv;
var type = args[2] || 'text';
var arr = []; 
var bufferString; 

function csvHandler(req, res){
  fs.readFile('people.csv',function (err,data) {

  if (err) {
    return console.log(err);
  }

  //Convert and store csv information into a buffer. 
  bufferString = data.toString(); 

  //Store information for each individual person in an array index. Split it by every newline in the csv file. 
  arr = bufferString.split('\n'); 
  console.log(arr); 

  for (i = 0; i < arr.length; i++) { 
    JSON.stringify(arr[i]); 
  }

  JSON.parse(arr); 
  res.send(arr);  
});
}

//More code ommitted

我的问题是,当我在 bufferString 上调用 .split('\n') 方法时,我是否真的将 CSV 行转换为 Javascript 对象,或者有其他方法吗?

【问题讨论】:

  • 是的,通过调用split(),您正在创建一个数组,它是一个 Javascript 对象。
  • 你的道路命名有些悲观,加油!

标签: javascript node.js csv


【解决方案1】:

通过这样做:

arr = bufferString.split('\n'); 

您将拥有一个包含所有行的数组作为字符串

["fname, lname, uid, phone, address","John, Doe, 1, 444-555-6666, 34 dead rd",...]

您必须使用.split(',') 再次将其用逗号分隔,然后将标题分开并将其推送到 Javascript 对象中:

var jsonObj = [];
var headers = arr[0].split(',');
for(var i = 1; i < arr.length; i++) {
  var data = arr[i].split(',');
  var obj = {};
  for(var j = 0; j < data.length; j++) {
     obj[headers[j].trim()] = data[j].trim();
  }
  jsonObj.push(obj);
}
JSON.stringify(jsonObj);

然后你会得到一个像这样的对象:

[{"fname":"John",
  "lname":"Doe",
  "uid":"1",
  "phone":"444-555-6666",
  "address":"34 dead rd"
 }, ... }]

看到这个FIDDLE

【讨论】:

  • 谢谢你。你能解释一下第二行的确切作用吗?标题是什么意思?
  • @GGMU arr[0] 是第一行,即标题所在的位置:fname, lname, ...split(','); 使用符号 , 作为分隔符将字符串分解为数组。
  • 啊,明白了。谢谢你。正是我想要的。
  • 这仅适用于示例。如果你有一个不同的 csv 字段中有换行符(2行地址或其他东西),代码会很糟糕
【解决方案2】:

使用 ES6/ES7 和一些函数式编程指南:

  • 所有变量都是const(不变性)
  • 使用map/reduce 而不是while/for
  • 所有功能都是箭头
  • 无依赖关系
// Split data into lines and separate headers from actual data
// using Array spread operator
const [headerLine, ...lines] = data.split('\n');

// Split headers line into an array
// `valueSeparator` may come from some kind of argument
// You may want to transform header strings into something more
// usable, like `camelCase` or `lowercase-space-to-dash`
const valueSeparator = '\t';
const headers = headerLine.split(valueSeparator);

// Create objects from parsing lines
// There will be as much objects as lines
const objects = lines
  .map( (line, index) =>
    line
      // Split line with value separators
      .split(valueSeparator)

      // Reduce values array into an object like: { [header]: value }
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
      .reduce(

        // Reducer callback 
        (object, value, index) => ({
          ...object,
          [ headers[index] ]: value,
        }),

        // Initial value (empty JS object)
        {}
      )
  );

console.log("Objects:", objects);

对于使用,作为分隔符和引号字符串值的CSV文件,你可以使用这个版本:

// Split data into lines and separate headers from actual data
// using Array spread operator
const [headerLine, ...lines] = data.split('\n');

// Use common line separator, which parses each line as the contents of a JSON array
const parseLine = (line) => JSON.parse(`[${line}]`);

// Split headers line into an array
const headers = parseLine(headerLine);

// Create objects from parsing lines
// There will be as much objects as lines
const objects = lines
  .map( (line, index) =>

    // Split line with JSON
    parseLine(line)

      // Reduce values array into an object like: { [header]: value } 
      .reduce( 
        (object, value, index) => ({
          ...object,
          [ headers[index] ]: value,
        }),
        {}
      ) 
  );

return objects;

注意:对于大文件,最好使用流、生成器、迭代器等。

【讨论】:

    【解决方案3】:

    您可以尝试使用 MVC Razor,

    <script type="text/javascript">
        MyNamespace.myConfig = @Html.Raw(Json.Encode(new MyConfigObject()));
    </script>
    

    Json.Encode 会将初始化的对象序列化为 JSON 格式。然后 Html.Raw 将阻止它将引号编码为 ".

    这里是整个example

    【讨论】:

    • 在将框架添加到依赖关系列表之前要明智地判断。特别是如果您只需要 CSV 阅读器。
    • 那个链接现在失效了。
    【解决方案4】:

    您可以使用 lodash(或下划线)来帮助解决此问题。

    var objects = _.map(arr, function(item){return item.split(',');});
    var headers = objects[0];
    objects.splice(0, 1); // remove the header line
    populatedObject = [];
    objects.forEach(function(item){
       var obj = _.zipObject(headers, item);
       populatedObject.push(obj);
    });
    

    .zipObject 方法会将每个标头与 items 数组中的每个值匹配并生成一个对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-12
      • 2012-08-01
      • 2012-06-30
      • 2013-03-12
      • 1970-01-01
      • 2021-12-19
      • 2021-11-21
      • 2020-01-07
      相关资源
      最近更新 更多