42

I have data in CSV format data 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. So please how can I implement it using Javascript.

mehmetseckin
  • 2,901
  • 1
  • 29
  • 40
Pankaj
  • 2,713
  • 4
  • 13
  • 21
  • 2
    Welcome to StackOverflow. Have you tried anything so far? Is it possible for you to show your code, even if it doesn't work? – mehmetseckin Jan 16 '15 at 07:19
  • 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 https://github.com/evanplaice/jquery-csv – Evan Plaice Jan 21 '16 at 14:16

6 Answers6

71

The below should work for you.

All credit to http://techslides.com/convert-csv-to-json-in-javascript

//var csv is the CSV file with headers
function csvJSON(csv){

  var lines=csv.split("\n");

  var result = [];

  // NOTE: 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)
  // jsfiddle showing the issue https://jsfiddle.net/
  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
}
Wesley Smith
  • 18,806
  • 20
  • 79
  • 127
  • 5
    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 Dec 06 '19 at 19:40
  • @matthew-e-brown Indeed it will. Good observation. – Wesley Smith Dec 06 '19 at 19:52
  • 7
    Perhaps take a look at my answer [here](https://stackoverflow.com/questions/59218548/what-is-the-best-way-to-convert-from-csv-to-json-when-commas-and-quotations-may/59219146#59219146), 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. :-) – matthew-e-brown Dec 06 '19 at 19:55
25

I would check out 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.

mareoraft
  • 2,915
  • 4
  • 23
  • 55
4

Base on @DelightedD0D, 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
}
foxiris
  • 2,563
  • 26
  • 30
  • 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"', }, ]``` – Simon Trichereau Aug 23 '21 at 09:40
4

I think, I have a better solution, this also have one issue i.e. the values should not contain comma(,). Otherwise it is a best solution.

 // 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);
};
}

Thank you

Badro Niaimi
  • 973
  • 1
  • 15
  • 26
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)
mplungjan
  • 155,085
  • 27
  • 166
  • 222
0

I have a similar answer like @DelightedD0D 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 @DelightedD0D's code to set the headers dynamically:

 for(var j=0;j<headers.length;j++){
          obj[headers[j]] = currentline[j];
      }
VeldMuijz
  • 595
  • 4
  • 18