Convert CSV's to JSON on the frontend

Photo by Ryland Dean on Unsplash

Convert CSV's to JSON on the frontend

no more "Cannot find module 'fs'

In The Before™️, it was easy to pick an NPM library that would take in an excel or CSV file and translate that file to JSON. However, choosing one nowadays is a bit trickier due to many frontend frameworks supporting webpack5 and dropping support for NodeJS polyfills--specifically the fs module.

In this post, our use case is to build an application that takes in a bulk set of items and uploads them to a database. We'll use the random user API to generate a CSV, but this can easily be an existing CSV of store products etc.

Project scaffolding

To keep the focus on manipulating CSV's, we'll have a starter repo to work with.

Clone the following repo, ensure you're on the main branch, and install the dependencies. Once done, open up the repo in your editor.

While the repo is nothing much, I took the liberty of creating a home page and an admin page with react-router-dom@6.

Upon running the app with npm start, navigate to the /admin page to see the following screen:

admin page with submit button and a file input

CSV conversion

Most NPM modules that try to convert a CSV to JSON rely on the built-in fs Node module to read the file. This module, however, is not available in the browser.

Fortunately, we'll use the papaparse library. This library doesn't rely on any external dependencies to perform isn't conversion.

Begin by installing the library:

npm i papaparse

Next, in the AdminPage.js file, import the useState effect, as well as the newly installed package:

import React, { useState } from 'react'
import Papa from 'papaparse'

Lastly, inside our AdminPage function, replace the two empty functions in the file with the following:

const [userJSON, setUserJSON] = useState()
    const [uploadedCSV, setUploadedCSV] = useState(null)

    const handleCSVSubmit = (e) => {
        e.preventDefault()

        Papa.parse(uploadedCSV, {
            header: true,
            complete: (results) => {
                console.log({ results })
                setUserJSON(results)
            },
        })
    }

    const handleCSVUpload = (e) => {
        console.log(e.target.files[0])
        setUploadedCSV(e.target.files[0])
    }

The handleCSVUpload function will be called in the above snippet whenever a user clicks the "Choose File" button from our input. After a file is uploaded and a user clicks submit, the file is converted to JSON.

To verify, we log out the results.

🗒️ header:true is passed in to tell the parser that the top fields in our CSV are item headers and not items themselves.

Testing the solution

If you don't have a CSV on file, an easy to grab one is by using the randomUser API to generate a seed of data:

randomuser.me/api/?format=csv&results=10

Once the file is downloaded, use the app to upload it and open up your devTools to view the result.

array of results

Conclusion

This project definitely falls under the "scratching my own itch" category since I spent plenty of time trying to find a reliable package to do my parsing.

Hope this helps and until next time Focus Otters!

Did you find this article valuable?

Support Michael Liendo by becoming a sponsor. Any amount is appreciated!