Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse CSV records in to an array of objects in JavaScript

I'm new to JS and not much exp in Regex to play with string manipulation.

Here is my CSV file with records in tabular form with the first line as headers and from on next line the values will be present:

Name  City   Country
John  Chennai IN
Ken   Brisban AUS
Ben   NY      US

I need the output in a array of objects like this:

[
{Name: 'John',City: "Chennai",Country:"IN"}
{Name: 'Ken',City: "Brisbane",Country:"AUS"}
{Name: 'Ben',City: "NY",Country:"US"}
]

I'm uploading a CSV file and need to save those records in to DB and below is the code block which will be triggered after I upload the CSV and I tried to parse the CSV records with below:

        $scope.processFiles = function() {
            //var input = document.getElementById("fileOutput");
            var input = document.querySelector('input[type = "file"]')
            var file = input.files[0];
            var reader = new FileReader();
            var output;
            reader.onload = function (e) {
                var csvToText = e.target.result;
                output = csvToJSON(csvToText);
                console.log(output);
            };
            reader.readAsText(file);
            event.preventDefault();
        }

        function csvToJSON(csv) {
            var lines = csv.split("\n");
            var result = [];
            var headers;
            for (var i = 0; i < lines.length; i++) {
                headers = lines[i].split("\n");
            }
            var cont = 0;
            for (var i = 0; i < lines.length; i++) {

                var obj = {};
                var currentline = lines[i].split("\n");
                for (var j = 0; j < headers.length; j++) {
                    obj[cont] = currentline[j];
                }
                cont++;
                result.push(obj);
            }
            console.log(result);
            //console.log(JSON.stringify(result));

            //return result;
        }

The output I'm getting is below i.e. the values are shown in one line with comma separators and the fourth array element is not supposed to display.

0: {0: "Name,City,Country"}
1: {1: "John,Chennai,IN"}
2: {2: "Ken,Brisbane,AUS"}
3: {3: "Ben,NY,USA"}
4: {4: ""}
like image 968
Mar1009 Avatar asked Oct 24 '25 05:10

Mar1009


2 Answers

I have corrected your function to return the output in the desired format:

function csvToJSON(csv) {
    var lines = csv.split("\n");
    var result = [];
    var headers;
    headers = lines[0].split(",");

    for (var i = 1; i < lines.length; i++) {
        var obj = {};

        if(lines[i] == undefined || lines[i].trim() == "") {
            continue;
        }

        var words = lines[i].split(",");
        for(var j = 0; j < words.length; j++) {
            obj[headers[j].trim()] = words[j];
        }

        result.push(obj);
    }
    console.log(result);
}
like image 191
Arun Selin Avatar answered Oct 25 '25 18:10

Arun Selin


First, parse the CSV text into an array:

function parseCsv (data) {
  const re = /(,|\r?\n|\r|^)(?:"([^"]*(?:""[^"]*)*)"|([^,\r\n]*))/gi
  const result = [[]]
  let matches
  while ((matches = re.exec(data))) {
    if (matches[1].length && matches[1] !== ',') result.push([])
    result[result.length - 1].push(
      matches[2] !== undefined ? matches[2].replace(/""/g, '"') : matches[3]
    )
  }
  return result
}

Then read the headers and return an array of objects:

function arrayToObject (csvArray) {

  //Take the first line (headers) from the array and remove it from the array.
  const headers = csvArray.shift() 

  // Iterate through the rows and reduce each column to an object
  return csvArray.map(row => headers.reduce((acc, currentHeader, i) => ({ ...acc, ...{ [currentHeader]: row[i] } }), {}))
}

How to use:

const csvArray = parseCsv(csvText)
const arrayOfObjects = arrayToObject(csvArray)

Thanks to Jezternz for the CSV parser

like image 35
Wilhelm Mauch Avatar answered Oct 25 '25 17:10

Wilhelm Mauch