JavaScript – How to Parse JSON to CSV and Vice Versa

I am converting an array of JS object to CSV by using below code

downloadCSVFromJson(filename, arrayOfJson) {
    // convert JSON to CSV
    const replacer = (key, value) => value === null ? '' : value // specify how you want to handle null values here
    const header = Object.keys(arrayOfJson[0]);
    let csv = arrayOfJson.map(row => header.map(fieldName =>
        JSON.stringify(row[fieldName], replacer)).join(','));
    csv.unshift(header.join(','));
    csv = csv.join('\r\n');

    // Create link and download
    var link = document.createElement('a');
    link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(csv));
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

And it is working as expected now I need to do vice versa csv to an array of objects to do the same I am using below approach

 handleUploadFinished() {
    this.showSpinner = true;

    [...this.template
        .querySelector('input[type="file"]')
        .files].forEach(async file => {
            try {
                const csv = await this.load(file);
                console.log(csv);

            } catch (e) {
                console.log('Error in Parsing CSV ' + e);
            }
        });
}

async load(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = function () {
            resolve(reader.result);
        };
        reader.onerror = function () {
            reject(reader.error);
        };
        reader.readAsText(file);
    });
}

without changing anything in the csv if I try to read it using the above code then I get below JSON

 "category,name,includeInAuto,srNumber,testType
"Test1","Name1","true",1,"type1"
"Test2","Name2","true",1,"type2"
"Test3","Name3","true",1,"type3"
"Test4","Name4","true",1,"type4"
"Test5","Name5","true",1,"type5"
"Test6","Name6","true",1,"type6"
"Test7","Name7","true",1,"type7"

but when I do changes in the CSV, file save it and then try to read it by using the same code above then I get whole ouput surrounded by double quotes as shown below

"category,name,includeInAuto,srNumber,testType 
Test1,Name1,true,1,type1 
Test2,Name2,true,2,type2
Test3,Name3,true,3,type3
Test4,Name4,true,4,type4
Test5,Name5,true,5,type5
Test6,Name6,true,6,type6
Test7,Name7,true,7,type7"

the problem is not just with the quotes coming or not but when I change name7 to name,7 then I get something like below

"category,name,includeInAuto,srNumber,testType 
    Test1,Name1,true,1,type1 
    Test2,Name2,true,2,type2
    Test3,Name3,true,3,type3
    Test4,Name4,true,4,type4
    Test5,Name5,true,5,type5
    Test6,Name6,true,6,type6
    Test7,\"Name,7\",true,6,type6"

Above whole csv string is in double quotes but the name name, 7 is also in double quotes with some extra slashes now instead of 4 comma separated values we have 5 comma separated values which is incorrect

by spending some time on google I came across with this JS library called papaParse, if anyone has used this js library then please do let me know how can I use in LWC I am familiar till adding it as static resource and then importing in JS but not sure how to call method from this library.

Best Answer

Here's a very simple CSV parsing demo from papaparse:

import { LightningElement } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import PAPA from '@salesforce/resourceUrl/papaparse';

export default class Q304122 extends LightningElement {
    ready = false;
    connectedCallback() {
        loadScript(this, PAPA)
        .then(()=>{this.ready=true;});
    }
    onchange(event) {
        [...event.target.files].forEach(file => {
            Papa.parse(file, {
                complete: results => { console.log(results); }
            });
        })
    }
}

<template>
    <input if:true={ready} type="file" multiple accept=".csv" onchange={onchange} />
    <lightning-spinner if:false={ready}>
    </lightning-spinner>
</template>

Simply download the papaparse.min.js file from PapaParse, upload it as a static resource (here called papaparse), then in your connectedCallback(), you load the script, and in a handler, you load the files. I chose an onchange handler, but it could easily be an onclick handler. Showing the spinner and other niceties are left as an exercise to the reader.

You'll want to read the documentation; Papa can also convert objects into CSV files as well!

Related Topic