Parsing a CSV file in ES6 JavaScript

There are a lot of libraries out there that parse CSV files for pretty much any language out there. JavaScript is no exception. When I was looking for one that was utilized ES6, I was hard pressed to find one. Since it is a fairly easy task, I decided to see what implementation of my own would look like.

It started out as a few methods but it quickly expanded into a small class. Parsing a line of a CSV file can be as easy as calling split(',') on the string but it is a little more involved if you want to include other characters inside your CSV files.

class Csv {
  parseLine(text) {
    const regex =
    /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;
    let arr = [];
    text.replace(regex, (m0, m1, m2, m3) => {
      if (m1 !== undefined) {
        arr.push(m1.replace(/\\'/g, "'"));
      } else if (m2 !== undefined) {
        arr.push(m2.replace(/\\"/g, "\""));
      } else if (m3 !== undefined) {
        arr.push(m3);
      }
      return "";
    });
    if (/,\s*$/.test(text)) {
      arr.push("");
    }
    return arr;
  }

  zipObject(props, values) {
    return props.reduce((prev, prop, i) => {
      prev[prop] = values[i];
      return prev;
    }, {});
  }

  parse(csv) {
    let [properties, ...data] = csv.split("\n").map(this.parseLine);
    return data.map((line) => this.zipObject(properties, line))
  };

  serialize(obj) {
    let fields = Object.keys(obj[0]);
    let csv = obj.map(row => fields.map((fieldName) => JSON.stringify(row[fieldName] || "")));
    return [fields, ...csv].join("\n");
  }; 
}

Passing a CSV string into pairs will return you an array of objects with the keys being the first line in the string. This is implemented by using the zipObject method I've detailed in another post.

The serialize method will turn a similarly structure object into a CSV string.

JsBin