95

I am trying to convert csv file to json. I am using .

Example CSV:

a,b,c,d
1,2,3,4
5,6,7,8
...

Desired JSON:

{"a": 1,"b": 2,"c": 3,"d": 4},
{"a": 5,"b": 6,"c": 7,"d": 8},
...

I tried node-csv parser library.But the output is like array not like I expected.

I'm using Node 0.8 and express.js and would like a recommendation on how to easily accomplish this.

2

21 Answers 21

126

Node.js csvtojson module is a comprehensive nodejs csv parser. It can be used as node.js app library / a command line tool / or browser with help of browserify or webpack.

the source code can be found at: https://github.com/Keyang/node-csvtojson

It is fast with low memory consumption yet powerful to support any of parsing needs with abundant API and easy to read documentation.

The detailed documentation can be found here

Here are some code examples:

Use it as a library in your Node.js application ([email protected] +):

  1. Install it through npm

npm install --save csvtojson@latest

  1. Use it in your node.js app:
// require csvtojson
var csv = require("csvtojson");

// Convert a csv file with csvtojson
csv()
  .fromFile(csvFilePath)
  .then(function(jsonArrayObj){ //when parse finished, result will be emitted here.
     console.log(jsonArrayObj); 
   })

// Parse large csv with stream / pipe (low mem consumption)
csv()
  .fromStream(readableStream)
  .subscribe(function(jsonObj){ //single json object will be emitted for each csv line
     // parse each json asynchronousely
     return new Promise(function(resolve,reject){
         asyncStoreToDb(json,function(){resolve()})
     })
  }) 

//Use async / await
const jsonArray=await csv().fromFile(filePath);

Use it as a command-line tool:

sh# npm install csvtojson
sh# ./node_modules/csvtojson/bin/csvtojson ./youCsvFile.csv

-or-

sh# npm install -g csvtojson
sh# csvtojson ./yourCsvFile.csv

For advanced usage:

sh# csvtojson --help

You can find more details from the github page above.

Sign up to request clarification or add additional context in comments.

7 Comments

Code has been added. See more detailed documentation here github.com/Keyang/node-csvtojson
Since version 0.3.0, csvtojson does not depend on any other lib. It will behave like a proper Stream object.
The link to the blog is dead.
I don't know if this is happening only to me, but for a large CSV file this is to slow. Like 10 seconds slower than d3
for ppl like me who are looking out for simpler version to read from web url, csv() .fromStream(request.get('example.com/test.csv')) .then((jsonArray) => { console.log(util.inspect(jsonArray)); }, (err)=>{ console.log(err); });
|
24

You can try to use underscore.js

First convert the lines in arrays using the toArray function :

var letters = _.toArray(a,b,c,d);
var numbers = _.toArray(1,2,3,4);

Then object the arrays together using the object function :

var json = _.object(letters, numbers);

By then, the json var should contain something like :

{"a": 1,"b": 2,"c": 3,"d": 4}

Comments

24

Had to do something similar, hope this helps.

// Node packages for file system
var fs = require('fs');
var path = require('path');


var filePath = path.join(__dirname, 'PATH_TO_CSV');
// Read CSV
var f = fs.readFileSync(filePath, {encoding: 'utf-8'}, 
    function(err){console.log(err);});

// Split on row
f = f.split("\n");

// Get first row for column headers
headers = f.shift().split(",");

var json = [];    
f.forEach(function(d){
    // Loop through each row
    tmp = {}
    row = d.split(",")
    for(var i = 0; i < headers.length; i++){
        tmp[headers[i]] = row[i];
    }
    // Add object to list
    json.push(tmp);
});

var outPath = path.join(__dirname, 'PATH_TO_JSON');
// Convert object to string, write json to file
fs.writeFileSync(outPath, JSON.stringify(json), 'utf8', 
    function(err){console.log(err);});

4 Comments

Or even var json = f.map(function(d, i){ ... return tmp; }
unfortunately splitting on newline won't work if any cell has a newline character within it 😅
solves 90% of the requirements
If a future reader needs a solution with support for newline characters, commas and fields with double quotes, look for my answer stackoverflow.com/a/76019283/12368402
13

Here is a solution that does not require a separate module. However, it is very crude, and does not implement much error handling. It could also use more tests, but it will get you going. If you are parsing very large files, you may want to seek an alternative. Also, see this solution from Ben Nadel.

Node Module Code, csv2json.js:

/*
 * Convert a CSV String to JSON
 */
exports.convert = function(csvString) {
    var json = [];
    var csvArray = csvString.split("\n");

    // Remove the column names from csvArray into csvColumns.
    // Also replace single quote with double quote (JSON needs double).
    var csvColumns = JSON
            .parse("[" + csvArray.shift().replace(/'/g, '"') + "]");

    csvArray.forEach(function(csvRowString) {

        var csvRow = csvRowString.split(",");

        // Here we work on a single row.
        // Create an object with all of the csvColumns as keys.
        jsonRow = new Object();
        for ( var colNum = 0; colNum < csvRow.length; colNum++) {
            // Remove beginning and ending quotes since stringify will add them.
            var colData = csvRow[colNum].replace(/^['"]|['"]$/g, "");
            jsonRow[csvColumns[colNum]] = colData;
        }
        json.push(jsonRow);
    });

    return JSON.stringify(json);
};

Jasmine Test, csv2jsonSpec.js:

var csv2json = require('csv2json.js');

var CSV_STRING = "'col1','col2','col3'\n'1','2','3'\n'4','5','6'";
var JSON_STRING = '[{"col1":"1","col2":"2","col3":"3"},{"col1":"4","col2":"5","col3":"6"}]';

/* jasmine specs for csv2json */
describe('csv2json', function() {

    it('should convert a csv string to a json string.', function() {
        expect(csv2json.convert(CSV_STRING)).toEqual(
                JSON_STRING);
    });
});

2 Comments

this one didn't work as well as csvtojson. When I had "Aug 23, 2016" it split aug23 and 2016 into different fields
Bummer. You could wrap the date in quotes to fix it?
6

If you want just a command line converter, the quickest and most clean solution for me is to use csvtojson via npx (included by default in node.js)

$ npx csvtojson ./data.csv > data.json

Comments

6

Using ES6

const toJSON = csv => {
    const lines = csv.split('\n')
    const result = []
    const headers = lines[0].split(',')

    lines.map(l => {
        const obj = {}
        const line = l.split(',')

        headers.map((h, i) => {
            obj[h] = line[i]
        })

        result.push(obj)
    })

    return JSON.stringify(result)
}

const csv = `name,email,age
francis,[email protected],33
matty,[email protected],29`

const data = toJSON(csv)

console.log(data)

Output

// [{"name":"name","email":"email","age":"age"},{"name":"francis","email":"[email protected]","age":"33"},{"name":"matty","email":"[email protected]","age":"29"}]

1 Comment

There is a leak of memory with your code
5

Using lodash:

function csvToJson(csv) {
  const content = csv.split('\n');
  const header = content[0].split(',');
  return _.tail(content).map((row) => {
    return _.zipObject(header, row.split(','));
  });
}

1 Comment

A tweak: I added .map(function(str) { return _.trim(str, '"') to remove any double-quotes from the headers and data items, ie const header = content[0].split(',').map(function(str) { return _.trim(str, '"'); }); and return _.zipObject(header, row.split(',').map(function(str) { return _.trim(str, '"'); }));
3

I haven't tried csv package https://npmjs.org/package/csv but according to documentation it looks quality implementation http://www.adaltas.com/projects/node-csv/

Comments

3

I started with node-csvtojson, but it brought too many dependencies for my linking.

Building on your question and the answer by brnd, I used node-csv and underscore.js.

var attribs;
var json:
csv()
    .from.string(csvString)
    .transform(function(row) {
        if (!attribs) {
            attribs = row;
            return null;
        }
        return row;
     })
    .to.array(function(rows) {
        json = _.map(rows, function(row) {
            return _.object(attribs, row);
        });
     });

3 Comments

async and underscore was too much for you?
@Spencer, at the time that I posted, the dependencies were different: github.com/Keyang/node-csvtojson/blob/… Pulling in express for a csv conversion felt unnatural
Oh, yeah that is a crazy dependency. My bad.
3

I have a very simple solution to just print json from csv on console using csvtojson module.

// require csvtojson
var csv = require("csvtojson");

const csvFilePath='customer-data.csv' //file path of csv
csv()
.fromFile(csvFilePath)``
.then((jsonObj)=>{
    console.log(jsonObj);
})

Comments

2

2023 Answer - Works for CSV files with linebreaks inside fields, and with separators (commas) inside fields aswell

I decided to write my own function for the following reasons:

  • csvtojson hasn't been updated since June 7th 2021, and contains calls to substr, which is deprecated and might fail on constrained environments.
  • plain JS functions available in the answers wouldn't work against my dataset, because it contains both commas inside fields and linebrakes inside fields, which are both supported by RFC 4180
  • Update: I realized my dataset also contained double quotes inside a field, which is valid if they are escaped with another double quote, so I updated my answer to account for it aswell. Example of valid double quotes: "Name ""Nickname"" LastName"
import fs from "fs";

function readCSV(filepath, separator = ",") {
  /** Reads a csv file, taking into consideration linebreaks inside of fields, and double quotes or no quotes.
   * Converts it into a json object
   */
  const fp = new URL(filepath, import.meta.url);
  const file = fs.readFileSync(fp, { encoding: "utf-8" });

  // Figure out how many cells there are by counting the first line. 
  // ATTENTION: If your header contains commas or a linebreak, this will fail.
  const firstLineBreak = file.indexOf("\n");
  const rowsNum = file.slice(0, firstLineBreak).split(",").length;

  // Construct a regex based on how many headers there are
  const singleCellRegex = `(?:(?:"([\\s\\S]*?)")|((?:(?:[^"${separator}\\n])|(?:""))+))`;
  let regexText = "";

  for (let i = 0; i < rowsNum; i++) {
    regexText += "," + singleCellRegex;
  }

  const regex = new RegExp(regexText.slice(1), "g");
  const results = file.matchAll(regex);

  const rowsArr = [];
  for (const row of results) {
    const newRow = [];

    for (let i = 0; i < rowsNum; i++) {
      const rowValue = row[2 * i + 1] ?? row[2 * i + 2];
      newRow.push(rowValue.replaceAll('""', '"')); // Remove double double quotes
    }

    rowsArr.push(newRow);
  }

  const headers = rowsArr[0];
  const rows = rowsArr.slice(1);

  return rows.map((row) =>
    row.reduce((jsonRow, field, idx) => {
      jsonRow[headers[idx]] = field;
      return jsonRow;
    }, {})
  );
}

Comments

1

I have used csvtojson library for converting csv string to json array. It has variety of function which can help you to convert to JSON.
It also supports reading from file and file streaming.

Be careful while parsing the csv which can contain the comma(,) or any other delimiter . For removing the delimiter please see my answer here.

Comments

1

Step 1:

Install node module: npm install csvtojson --save

Step 2:

var Converter = require("csvtojson").Converter;

var converter = new Converter({});

converter.fromFile("./path-to-your-file.csv",function(err,result){

    if(err){
        console.log("Error");
        console.log(err);  
    } 
    var data = result;

    //to check json
    console.log(data);
});

Comments

1

npm install csvjson --save
In you Node JS File

const csvjson = require('csvjson');
convertCSVToJSON(*.csv);

convertCSVToJSON = (file) => {
  const convertedObj = csvjson.toObject(file);
}

Comments

1

Node-ETL package is enough for all BI processing.

npm install node-etl; 

Then :

var ETL=require('node-etl');
var output=ETL.extract('./data.csv',{
              headers:["a","b","c","d"],
              ignore:(line,index)=>index!==0, //ignore first line
 });

2 Comments

The link to this library is dead - perhaps it was moved to somewhere else on Github (or forked?). Please update link.
Thank you @RohitParte . This is one of my first modules in NodeJs. While some features work fine, it is missing a lot of features. I become extremely busy with other things (Reliability Engineering, DevOps, .. so on).
0

Use csv parser library, I'm explaining in more details how to use it here .

var csv = require('csv');
csv.parse(csvText, {columns: true}, function(err, data){
    console.log(JSON.stringify(data, null, 2));
});

Comments

0

csvtojson module is a comprehensive nodejs csv parser to convert csv to json or column arrays. It can be used as node.js library / command line tool / or in browser. Below are some features:

/** csv file
a,b,c
1,2,3
4,5,6
*/
const csvFilePath='<path to csv file>'
const csv=require('csvtojson')
csv()
.fromFile(csvFilePath)
.then((jsonObj)=>{
    console.log(jsonObj);
    /**
     * [
     *  {a:"1", b:"2", c:"3"},
     *  {a:"4", b:"5". c:"6"}
     * ]
     */ 
})
 
// Async / await usage
const jsonArray=await csv().fromFile(csvFilePath);

Comments

0

I converted a large (315 MB) csv file to json by installing the csvtojson module and then using the below code:

const fs = require('fs')
const Converter = require('csvtojson').Converter
const csvConverter = new Converter({
    constructResult:false,
    downstreamFormat:"array",
})

csvConverter.subscribe=function(json,row,index){
    json["rowIndex"]=index
};

const readStream = fs.createReadStream('./data.csv') // my csv file
const writeStream = fs.createWriteStream('./data.json') // my new json file

readStream.pipe(csvConverter).pipe(writeStream)

The resulting json file is in the desired format:

[
{"a": 1,"b": 2,"c": 3,"d": 4},
{"a": 5,"b": 6,"c": 7,"d": 8},
]

Comments

0

Once figured out how to csv data into two dimention array:

[['header1','header2'],['data1','data2']]

Convert to json is simply map and reduce:

const keys = input[0]
const jsonOutput = input.slice(1)
  .map(arr2 => keys.reduce((accumulator, element, index) => {
    return { ...accumulator,
      [element]: arr2[index]
    };
  }, {}))

Comments

0

In my case JSON.stringify didn't help as the files where too big. This solved my needs:

let csvFile = fs.readFileSync(
  csvFilePath,
  { encoding: "utf-8" },
  function (err) {
    console.log(err);
  }
);
csvFile = csvFile.split("\n");

let strFile = "export default [";
csvFile.forEach(function (d) {
  let row = d.split(",");
  strFile += `[${row}],`;
});
strFile += "]";

Comments

-2
let
    Source = Folder.Files("C:\Path\To\Your\Folder"),
    #"Filtered Hidden Files1" = Table.SelectRows(Source, each [Attributes]?[Hidden]? <> true),
    #"Invoke Custom Function1" = Table.AddColumn(#"Filtered Hidden Files1", "Transform File", each #"Transform File"([Content])),
    #"Removed Other Columns1" = Table.SelectColumns(#"Invoke Custom Function1", {"Name", "Transform File"}),
    #"Expanded Table Column1" = Table.ExpandTableColumn(#"Removed Other Columns1", "Transform File", Table.ColumnNames(#"Transform File"(#"Sample File"))),
    Grouped = Table.Group(#"Expanded Table Column1", {"CNR dept", "license report"}, {{"StateCounty", each _, type table [state=nullable text, county=nullable text]}}),
    AddCustom = Table.AddColumn(Grouped, "Custom", each [
        CNR = [CNR dept],
        dept = "test1",
        license = Record.FromList(
            List.Transform(
                Table.ToRecords([StateCounty]),
                each [
                    licenseType = [license report],
                    state = Record.FromList(
                        List.Transform(
                            List.Distinct([StateCounty][state]),
                            each _,
                            each List.Select([StateCounty][county], each [state] = _)
                        ),
                        List.Distinct([StateCounty][state])
                    )
                ]
            ),
            List.Distinct([StateCounty][license report])
        )
    ]),
    RemoveOtherColumns = Table.SelectColumns(AddCustom, {"Custom"}),
    ConvertToJSON = Json.FromValue(RemoveOtherColumns[Custom])
in
    ConvertToJSON

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.