# Convert CSV's to JSON on the frontend

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](https://github.com/Keyang/node-csvtojson/issues/285)--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](https://randomuser.me/) 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.

%[https://github.com/Focus-Otter/batch-upload]

 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1654576623476/1gC0LOZzC.png align="left")

# 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](https://www.npmjs.com/package/papaparse) library. This library doesn't rely on _any_ external dependencies to perform isn't conversion.

Begin by installing the library:

```js
npm i papaparse
```

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

```js
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:

```js
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:

https://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](https://cdn.hashnode.com/res/hashnode/image/upload/v1654577978820/nFkjvdByP.png align="left")

# 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! 
