Skip to content

Instantly share code, notes, and snippets.

@AyresMonteiro
Created May 29, 2023 21:40
Show Gist options
  • Save AyresMonteiro/a69876459a13e801033ffc470ba23964 to your computer and use it in GitHub Desktop.
Save AyresMonteiro/a69876459a13e801033ffc470ba23964 to your computer and use it in GitHub Desktop.
CSV to JSON utilities
const fs = require("fs");
const notEmpty = (line) => line !== "\n";
const trim = (str) => str.trim();
const EOL = /\r/;
const commaReg = /, ?/;
function normalizeProp(prop) {
const splitted = prop
.split(" ")
.map((word) => word.trim().toLocaleLowerCase());
return [
...[splitted.shift()],
...splitted.map((word) => {
let newWord = [...word].filter((letter) => /^[a-z]$/i.test(letter));
let tmpWord = [...newWord];
newWord[0] = tmpWord[0].toLocaleUpperCase();
return newWord.join("");
}),
].join("");
}
function readLineValues(line, lineNumber) {
let str = line;
let tmpStr = "";
let values = [];
let flag = false;
for (let char of str) {
if (char === '"' && !flag) flag = true;
else if (char === '"' && flag) flag = false;
if (commaReg.test(char) && !flag) {
values = [...values, tmpStr];
tmpStr = "";
continue;
}
if (char !== '"') tmpStr += char;
}
if (flag === true) {
throw new Error(
"invalid format" +
(lineNumber !== undefined ? " at line " + lineNumber : "")
);
}
const trimmed = values.map(trim);
return trimmed;
}
function csvToArray(csv, options = { enableNestedArrays: true }) {
const [rawHeaders, ...lines] = csv
.toString()
.split(EOL)
.filter(notEmpty)
.map(trim);
if (!lines.length) throw new Error("invalid csv!");
const headers = readLineValues(rawHeaders).map(normalizeProp);
const array = lines.map((item, idx) => {
const values = readLineValues(item, idx + 2);
const obj = headers.reduce((prev, header, idx) => {
if (values[idx].includes(", ") && options.enableNestedArrays) {
return {
...prev,
[header]: values[idx].split(commaReg).map(trim),
};
}
return { ...prev, [header]: values[idx] };
}, {});
return obj;
});
return array;
}
function csvToJSON(csv, options = { enableNestedArrays: true }) {
return JSON.stringify(csvToArray(csv, options));
}
function csvFileToArray(file_path, options = { enableNestedArrays: true }) {
const csv = fs.readFileSync(file_path);
return csvToArray(csv, options);
}
function csvFileToJSON(file_path) {
const csv = fs.readFileSync(file_path);
return csvToJSON(csv);
}
module.exports = {
csvToArray,
csvToJSON,
csvFileToArray,
csvFileToJSON,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment