I am getting a below structure after converting a CSV file to a JS object
"category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"
And I am trying to convert it like below
[{"category": "Test1", "name": "Name1", "includeInAuto": "true", "srNumber": 1 "testType": "type1"},
{"category": "Test2", "name": "Name2", "includeInAuto": "true", "srNumber": 2 "testType": "type2"},
{"category": "Test3", "name": "Name3", "includeInAuto": "true", "srNumber": 3 "testType": "type3"},
{"category": "Test4", "name": "Name4", "includeInAuto": "true", "srNumber": 4 "testType": "type4"},
{"category": "Test5", "name": "Name5", "includeInAuto": "true", "srNumber": 5 "testType": "type5"},
{"category": "Test6", "name": "Name6", "includeInAuto": "true", "srNumber": 6 "testType": "type6"},
{"category": "Test7", "name": "Name7", "includeInAuto": "true", "srNumber": 7 "testType": "type7"}]
I have tried using map like Object.entries(obj); or Object.keys(obj); or converting it an array first Array.from(obj) but not getting an expected result.
above all approaches separates each word to a single character like category to "c","a","t","e","g","o","r","y"
Can someone please help me to achieve the same?
UPDATE
if I edit the csv file in excel and then try to parse it then I get a below structure where instead of surrounding all the values with double quotes whole data is surrounded in double quotes as below
"category,name,includeInAuto,srNumber,testType
Test1,Name1,true,1,type1
Test2,Name2,true,2,type2
Test3,Name3,true,3,type3
Test4,Name4,true,4,type4
Test5,Name5,true,5,type5
Test6,Name6,true,6,type6
Test7,Name7,true,7,type7"
if instead of above any of the value has any special character in it lets assume if I change name7 to name,7 then FileReader return below structure
"category,name,includeInAuto,srNumber,testType
Test1,Name1,true,1,type1
Test2,Name2,true,2,type2
Test3,Name3,true,3,type3
Test4,Name4,true,4,type4
Test5,Name5,true,5,type5
Test6,Name6,true,6,type6
Test7,\"Name,7\",true,6,type6"
in above whole csv string is in double quotes but the name name, 7 is also in double quotes with some extra slashes now instead of 4 comma separated values we have 5 comma separated values.
4 Answers 4
I would suggest using a dedicated CSV parser, like PapaParse, this is exactly what they are designed to do.
Parsing CSV data can get really tricky once you get into quoting etc.
let csv = `category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"`;
let result = Papa.parse(csv, { header: true, dynamicTyping: true });
console.log("Result:", result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>
2 Comments
Here is my try on your SPECIFIC example WITH qoutes
const parseCsv = csv => {
let lines = csv.split("\n");
const header = lines.shift().split(",")
return lines.map(line => {
const bits = JSON.parse("[" + line + "]")
let obj = {};
header.forEach((h, i) => obj[h] = bits[i]); // or use reduce here
// optional:
obj["includeInAuto"] = obj["includeInAuto"] === "true";
return obj;
});
};
const csv = `category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"`
console.log(parseCsv(csv));
Without quotes:
const parseCsv = csv => {
let lines = csv.split(/\r?\n/);
const header = lines.shift().split(",")
return lines.map(line => {
const bits = line.split(",")
let obj = {};
header.forEach((h, i) => obj[h] = bits[i]); // or use reduce here
// optional:
obj["includeInAuto"] = obj["includeInAuto"] === "true";
return obj;
});
};
const csv = `category,name,includeInAuto,srNumber,testType
Test1,Name1,true,1,type1
Test2,Name2,true,1,type2
Test3,Name3,true,1,type3
Test4,Name4,true,1,type4
Test5,Name5,true,1,type5
Test6,Name6,true,1,type6
Test7,Name7,true,1,type7`
console.log(parseCsv(csv));
With escaped quotes
const parseCsv = csv => {
let lines = csv.slice(1,csv.length-1).split(/\r?\n/);
console.log(lines)
const header = lines.shift().split(",")
return lines.map(line => {
const bits = line.trim().split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
let obj = {};
header.forEach((h, i) => obj[h] = bits[i].replace(/\"/g,"")); // or use reduce here
// optional:
obj["includeInAuto"] = obj["includeInAuto"] === "true";
return obj;
});
};
const csv = `"category,name,includeInAuto,srNumber,testType
Test1,Name1,true,1,type1
Test2,Name2,true,2,type2
Test3,Name3,true,3,type3
Test4,Name4,true,4,type4
Test5,Name5,true,5,type5
Test6,Name6,true,6,type6
Test7,\"Name,7\",true,6,type6"`
console.log(parseCsv(csv));
1 Comment
There are several ways to do this. Here's a snippet that uses a reducer for the csv-lines. If the csv gets more complex (e.g. nested " etc), you may want to write a parser (it's fun!) or use some external library to parse csv-files.
const csv = `category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"`.split("\n");
// get headers
const headers = csv[0].split(",");
// helper to create a row from values
// (using the just created headers)
const createRow = values => headers.reduce( (acc, header, i) =>
({...acc, [header]: values[i]}), {});
// reduce csv-lines to Array of Objects
const csv2Obj = csv
.slice(1) // no need for headers ofcourse
.reduce( (acc, row) => ([...acc, createRow(row.replace(/"/g, "").split(","))]), []);
console.log(csv2Obj);
.as-console-wrapper { top: 0; max-height: 100% !important; }
4 Comments
\n?csv2Obj should be generated with or without quotes around the csv values. The error you get is not related to the snippet code, but to something you are doing with JSON (JSON is not a part of the given snippet).Here is my solution to solve this.
let csv = `category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"`;
let data = csv.split("\n");
let title = data.shift().split(",");
let array = data.reduce((arr, row) => {
row = row.replace(/"/g, "");
let innerObj = row.split(",").reduce((obj, item, index) => {
obj[title[index]] = item;
return obj;
}, {});
arr.push(innerObj);
return arr;
}, []);
console.log(array);
2 Comments
"Test1","Surname1, FirstName1","true",1,"type1" - this is not a good idea: row = row.replace(/"/g, ""); see my version for a better way
csv-parseif that is okay