将CSV行转换为Javascript对象

convert CSV lines into Javascript objects

本文关键字:Javascript 对象 转换 CSV      更新时间:2023-11-18

我有一个简单的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对象,或者有其他方法吗?

这样做:

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

使用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;

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

您可以尝试使用MVC Razor、

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

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

这里是整个示例

您可以使用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数组中的每个值相匹配,并生成一个对象。

如果您已经有了一个数组,并且希望csv标头(第一行)是对象的属性,那么这里有一个解决方案。


const csvArrayToObj = (csvData) => {
  return csvData
    .map((csvLine, csvIndex) => {
      if (csvIndex === 0 || !csvLine.length) return null; // skip header and empty lines
      return csvLine.reduce((a, v, i) => ({ ...a, [csvData[0][i]]: v }), {});
    })
    .filter((filter) => !!filter); //filter empty lines
};
const csvArray = [
  ['name', 'age'],
  ['John Doe', 20],
  ['Jane Doe', 30],
];
csvArrayToObj(csvArray);
// output
[
    {
        "name": "John Doe",
        "age": 20
    },
    {
        "name": "Jane Doe",
        "age": 30
    }
]