58

I have data in CSV format and want to convert into JSON format using JavaScript.

Following are csv format:

[Test.csv] 
id;name;author
integer;string;authors:n
1;To Kill an Angry Bird;1

[authors.csv] 
id;name
integer;string
1;Harper Lee
2;JRR Tolkien
3;William Shakespeare

I want to get all the books with their authors. How can I implement it using JavaScript?

1
  • Use jquery-csv, specifically toArrays() to convert the CSV to convert to in-memory data. Then call JSON.stringify() to convert it to JSON. Here's the link to jquery-csv github.com/evanplaice/jquery-csv Commented Jan 21, 2016 at 14:16

8 Answers 8

88

The below should work for you.

All credit to Convert CSV to JSON in JavaScript (archived), by iwek:

//var csv is the CSV file with headers
function csvJSON(csv){
 
  var lines=csv.split("\n");
 
  var result = [];
 
  var headers=lines[0].split(",");
 
  for(var i=1;i<lines.length;i++){
 
     var obj = {};
     var currentline=lines[i].split(",");
 
     for(var j=0;j<headers.length;j++){
         obj[headers[j]] = currentline[j];
     }
 
     result.push(obj);
 
  }
  
  //return result; //JavaScript object
  return JSON.stringify(result); //JSON
}

If your columns contain commas in their values, you'll need to deal with those before doing the next step (you might convert them to &&& or something, then covert them back later).

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

5 Comments

This will go awry if the string in-between any delimiters is a quoted string with those delimiters. Like a quoted sentence with a comma, since it will split at the comma inside the string instead of ignoring the ones inside quotes.
@matthew-e-brown Indeed it will. Good observation.
Perhaps take a look at my answer here, the question that led me here in the first place? I don't exactly wish to copy-paste my answer over, since this answer works well for most cases, but I think just leaving this link in the comments may help others in the future if they're in this edge case. :-)
Can u tell me how do I convert CSV to JSON and add a parent node here is my CSV drive.google.com/file/d/1mQGqoXuxkLHAfJ4mrQMIB90apg9LiC1X/… here is the exact JSON format I want drive.google.com/file/d/1U_UoZhlM2CyJiGZ9nT0UqaXq-FuMuIJm/… ,u may think that if i have already converted the CSV to JSON why I'm asking to do it in programmatically,because when I'm converting the CSV to JSON the online converter is creating some issues with special characters and replacing it to this � ,so I was thinking to do it programmatically without this symbol error
The first challenge among others is to avoid special characters contained in a cell. your code failed at this first obstacle.
34

I would check out PapaParse. They have a file called papaparse.min.js that you can drop into your project if need be. PapaParse has no dependencies.

I have used it myself and can verify it works, is convenient, and is well-documented.

Comments

8

Based on the code by iwek re-shared in Wesley Smith's answer, I would add if (!lines[i]) continue so it can ignore any empty line and trailing lines.

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

    for (let i = 1; i < lines.length; i++) {        
        if (!lines[i])
            continue
        const obj = {}
        const currentline = lines[i].split(',')

        for (let j = 0; j < headers.length; j++) {
            obj[headers[j]] = currentline[j]
        }
        result.push(obj)
    }
    return result
}

2 Comments

This is the result I retrieve from my CSV ... I think you forgot to take count of quotes formatted CSV files [ { '"foo"': '"bar"', '"created"': '"2021-08-09 13:44:42"', '"price"': '"10.00"', }, ]
we have created online tool using above code, which anyone can refer here: minify-beautify.com/online-csv-to-json-convert
6

This solution fixed the comma issue.

function csvJSON(text, quoteChar = '"', delimiter = ',') {
    var rows=text.split("\n");
    var headers=rows[0].split(",");

    const regex = new RegExp(`\\s*(${quoteChar})?(.*?)\\1\\s*(?:${delimiter}|$)`, 'gs');
  
    const match = line => [...line.matchAll(regex)]
      .map(m => m[2]) 
      .slice(0, -1); 
  
    var lines = text.split('\n');
    const heads = headers ?? match(lines.shift());
    lines = lines.slice(1);
    
    return lines.map(line => {
      return match(line).reduce((acc, cur, i) => {
        // replace blank matches with `null`
        const val = cur.length <= 0 ? null : Number(cur) || cur;
        const key = heads[i] ?? `{i}`;
        return { ...acc, [key]: val };
      }, {});
    });
  }

var csvtojson = csvJSON(SOME_CSV_DATA);
console.log(csvtojson)

Comments

5

This solution has one issue i.e. the values should not contain comma(,):

 // convert csv to json
csvJSON(csvText) {
let lines = [];
const linesArray = csvText.split('\n');
// for trimming and deleting extra space 
linesArray.forEach((e: any) => {
    const row = e.replace(/[\s]+[,]+|[,]+[\s]+/g, ',').trim();
    lines.push(row);
});
// for removing empty record
lines.splice(lines.length - 1, 1);
const result = [];
const headers = lines[0].split(",");

for (let i = 1; i < lines.length; i++) {

    const obj = {};
    const currentline = lines[i].split(",");

    for (let j = 0; j < headers.length; j++) {
    obj[headers[j]] = currentline[j];
    }
    result.push(obj);
}
//return result; //JavaScript object
// return JSON.stringify(result); //JSON
return result;
}

// For Reading CSV File
readCSV(event) {
const reader = new FileReader();
reader.readAsText(event.files[0]);
reader.onload = () => {
    const text = reader.result;
    const csvToJson = this.csvJSON(text);
    console.log(csvToJson);
};
}

2 Comments

Can u tell me how do I convert CSV to JSON and add a parent node here is my CSV drive.google.com/file/d/1mQGqoXuxkLHAfJ4mrQMIB90apg9LiC1X/… here is the exact JSON format I want drive.google.com/file/d/1U_UoZhlM2CyJiGZ9nT0UqaXq-FuMuIJm/… ,u may think that if i have already converted the CSV to JSON why I'm asking to do it in programmatically,because when I'm converting the CSV to JSON the online converter is creating some issues with special characters and replacing it to this � ,so I was thinking to do it programmatically without this symbol error
please reffer this to know more reddit.com/r/androiddev/comments/vftmlq/…
3

Here is my try on your SPECIFIC example. I know it is an old question but I have used current methods

const titlesCsv = `id;name;author
integer;string;authors:n
1;To Kill an Mockingbird;1
2;Lord of the Rings;2
3;Hamlet;3`

const authorsCsv = `id;name
integer;string
1;Harper Lee
2;JRR Tolkien
3;William Shakespeare`

const parseCsv = csv => {
  let lines = csv.split("\n");
  const header = lines.shift().split(";")
  lines.shift(); // get rid of definitions
  return lines.map(line => {
    const bits = line.split(";")
    let obj = {};
    header.forEach((h, i) => obj[h] = bits[i]); // or use reduce here
    return obj;
  })
};
const titles = parseCsv(titlesCsv)
const authors = parseCsv(authorsCsv)
const books = titles.map(title => {
  return {
    id: title.id,
    name: title.name,
    author: authors.find(author => author.id === title.author).name
  }
})

console.log(books)

Comments

2

Here is an improved version of Sandeep Sherpur's answer. This version handles:

  1. comma (,) and double quotes (") inside the value fields
  2. empty fields
  3. empty lines and useless spaces
  4. extra or missing commas
function csvToJson(text, quoteChar = '"', delimiter = ",") {
    text = text.trim()
    let rows = text.split("\n")
    let headers = rows[0].split(",")

    const regex = new RegExp(`\\s*(${quoteChar})?(.*?)\\1\\s*(?:${delimiter}|$)`, "gs")

    const match = (line) => {
        const matches = [...line.matchAll(regex)].map((m) => m[2])
        // Ensure matches length matches headers length by padding with null values
        const paddedMatches = Array.from({ length: headers.length }, (_, i) => matches[i] ?? null)
        return paddedMatches
    }

    let lines = text.split("\n")
    const heads = headers ?? match(lines.shift())
    lines = lines.slice(1)

    return lines.map((line) => {
        return match(line).reduce((acc, cur, i) => {
            // replace blank matches with `null`
            const val = cur === null || cur.length <= 0 ? null : Number(cur) || cur
            const key = heads[i] ?? `{i}`
            return { ...acc, [key]: val }
        }, {})
    })
}

const csvString = `
aa,bb,cc
11,22,33
44,
77,,99
`

const jsonData = csvToJson(csvString)
console.log(jsonData)

Comments

0

I have a similar answer like the code by iwek re-shared in Wesley Smith's answer, but my code can be used in conjunction with Excel directly (copy and paste from Excel into a textarea).

function csvUpload(csvText){
        //Split all the text into seperate lines on new lines and carriage return feeds
        var allTextLines = csvText.split(/\r\n|\n/);
        //Split per line on tabs and commas
        var headers = allTextLines[0].split(/\t|,/);
        var lines = [];
        var locations = [];

        for (var i=1; i<allTextLines.length; i++) {
            var data = allTextLines[i].split(/\t|,/);
            
            if (data.length == headers.length) {
                                    
            var location = {"device_id":data[0], "address":data[1], "city":data[2]};
            locations.push(location);

            }

        }
        return locations;
    }

This way you can use a CSV that is copied into Excel. Excel will remove the seperators like , and others and will insert newlines etc.

With the my code you can pass everything into a textfield directly from Excel and then use that to create a json.

I have the naming of the fields static here, but you could use iwek's code to set the headers dynamically:

for(var j=0;j<headers.length;j++){
    obj[headers[j]] = currentline[j];
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.