This function converts a Javascript Object into a CSV.
var dataFromAPI = [{"name":"first"},{"name":"sec,ond"},{"name":"third 'jibberish"},{"name":"fourth, jibberish"}]
function convertToCSVandDownload(objArray) {
var csvOutput = "";
Object.keys(objArray).forEach(function(key) {
if (csvOutput.length == 0) {
csvOutput = "Index,Field Value\n";
csvOutput = csvOutput + JSON.stringify(key) + "," + JSON.stringify(objArray[key]["name"]) + "\n";
} else {
csvOutput = csvOutput + JSON.stringify(key) + "," + JSON.stringify(objArray[key]["name"]) + "\n";
}
})
return csvOutput;
}
console.log(convertToCSVandDownload(dataFromAPI));
3 Answers 3
Description
It would appear that your current solution is a bit complicated. Using JSON.parse
just to ensure that you escape ,
is overkill.
The overall solution can be drastically simplified as you will see in this post.
const
before let
and let
before var
All variables should be declared by default with const
. If a variable is going to be mutated then use let
. Don't use var
unless that is what you intended.
/// bad
var dataFromAPI = ...
/// good
const dataFromAPI = ...
note: pushing an element to a list will only mutate the array and not the variable, thus no error
Work with arrays and not with strings.
/// bad
csvOutput = "Index,Field Value\n";
/// good
const csvOutput = [
["Index", "Field", "Value"]
];
Function names should describe what they do.
The convertToCSVandDownload
method only converts to CSV but doesn't download. Change the name to convertToCSV
Working Solution
Use Array#reduce, destructuring assignment, Array#map, Array#join and spread syntax
const dataFromAPI = [{"name":"first"},{"name":"sec,ond"},{"name":"third 'jibberish"},{"name":"fourth, jibberish"}]
function convertToCSV(data, headers) {
return data
.reduce((a,{name},i)=>[...a, [i, `"${name}"`]], [headers])
.map(row=>row.join(","))
.join("\n");
}
const res = convertToCSV(dataFromAPI, ["Index", "Field Value"]);
console.log(res)
I'd like to propose a solution using flatMap
. Be aware that this is definitely not a cross-browser solution.
Let's create a function that given n arguments returns a CSV line:
const row = (...args) => args.map(JSON.stringify).join(',');
console.log(row('foo'));
console.log(row('foo', 'bar'));
console.log(row('foo', 'bar', 'baz'));
Then let's use flatMap
to append (or prepend) stuff while we map over an array. e.g.:
const pair = arr => arr.flatMap(n => [n, n]);
console.log(pair([1]));
console.log(pair([1, 2]));
console.log(pair([1, 2, 3]));
As you can see we can use flatMap
to "add" more items as we iterate. Let's use this to add the headers during the first iteration.
Complete solution
const dataFromAPI = [
{"name": "first"},
{"name": "sec,ond"},
{"name": "third 'jibberish"},
{"name": "fourth, jibberish"}];
const row = (...args) => args.map(JSON.stringify).join(',');
const csv =
dataFromAPI
.flatMap((obj, idx) =>
idx === 0 ?
[row('Index', 'Field Value'), row(idx, obj.name)] :
[row(idx, obj.name)])
.join('\n');
console.log(csv);
Skimming through your code I believe ya may not need that if
/else
check within the .forEach
loop...
var dataFromAPI = [{"name":"first"},{"name":"sec,ond"},{"name":"third 'jibberish"},{"name":"fourth, jibberish"}]
function convertToCSVandDownload(objArray) {
var csvOutput = "Index,Field Value\n";
Object.keys(objArray).forEach(function(key) {
csvOutput = csvOutput + JSON.stringify(key) + "," + JSON.stringify(objArray[key]["name"]) + "\n";
})
return csvOutput;
}
console.log(convertToCSVandDownload(dataFromAPI));
... and one thing that might be an improvement may be allowing for converting other target_key
s...
var dataFromAPI = [{"name":"first"},{"name":"sec,ond"},{"name":"third 'jibberish"},{"name":"fourth, jibberish"}]
function convertToCSVandDownload(objArray, target_key) {
var csvOutput = "Index,Field Value\n";
Object.keys(objArray).forEach(function(i) {
csvOutput += JSON.stringify(i) + "," + JSON.stringify(objArray[i][target_key]) + "\n";
})
return csvOutput;
}
console.log(convertToCSVandDownload(dataFromAPI, 'name'));
... other than those two things I think you code is good, and the only other thing ya might want to consider is what ya want to do with data structures that have more layers than dataFromAPI
-
1\$\begingroup\$ Is 'ya' Jamaican? \$\endgroup\$dfhwze– dfhwze2019年06月18日 18:36:50 +00:00Commented Jun 18, 2019 at 18:36
-
\$\begingroup\$ The urbandictionary says something like "Term for "yes" used in Jamaica", but that is just something that I read online somewhere. Personally I use it for that as well as a less direct form of
you
, eg. "ya ya could do that', which when spoken would have a moreuh
like sound on the secondya
. \$\endgroup\$S0AndS0– S0AndS02019年06月18日 18:43:46 +00:00Commented Jun 18, 2019 at 18:43