How to write a CSV file with Node.js

By

Learn how to write a CSV file with Node.js using the objects-to-csv package: turn an array of objects into a file with toDisk() and append new rows.

~~~

A great library you can use to quickly write an array of objects to a CSV file using Node.js is objects-to-csv. You give it the array, it figures out the columns from the object properties, and it writes the file.

Many other libraries exist, of course. I found this one useful for a project of mine where I had to generate a one-time CSV file, so I wrote this little tutorial.

Using a stream-based library like fast-csv might suits your needs in more performance-oriented applications, for example when you export a huge number of rows. For a one-shot export, objects-to-csv is all you need.

Install it using:

npm install objects-to-csv

then require it in your Node.js code:

const ObjectsToCsv = require('objects-to-csv')

When you have an array of objects ready to write to CSV, initialize a new ObjectsToCsv object instance:

const csv = new ObjectsToCsv(list)

then call csv.toDisk(), passing the file you want to write to (relative to your app base path):

await csv.toDisk('./list.csv')

This is a promise-based API and I used await, so you need to call this inside an async function.

Here’s a complete example you can run:

const ObjectsToCsv = require('objects-to-csv')

const people = [
  { name: 'Flavio', age: 37 },
  { name: 'Roger', age: 8 }
]

async function saveCsv() {
  const csv = new ObjectsToCsv(people)
  await csv.toDisk('./people.csv')
}

saveCsv()

The resulting people.csv file contains:

name,age
Flavio,37
Roger,8

The column names in the CSV are automatically inferred from the object properties names.

How are the columns picked?

Be careful here: the columns come from the first object in the array. If a later object has an extra property, that value is silently dropped. You get no error and no warning.

const people = [
  { name: 'Flavio', age: 37 },
  { name: 'Roger', age: 8, city: 'Milan' }
]

Writing this to disk gives you only the name and age columns. city disappears.

The fix is the allColumns option, which scans every object for keys:

await csv.toDisk('./people.csv', { allColumns: true })

Now the file has a city column, left empty for the rows that don’t have that property. Notice that with allColumns the columns are sorted alphabetically, so the order changes.

How do you append rows?

toDisk() overwrites the existing content of the file. To append to that file, pass a second object with the append property set to true:

await csv.toDisk('./list.csv', { append: true })

The header row is written only once. When you append to a file that already has content, only the new rows are added.

Getting the CSV as a string

Sometimes you don’t want a file at all. Maybe you’re sending the CSV as an HTTP response. In that case, call toString():

const output = await csv.toString()

You get back the same content toDisk() would write, header included.

If you’re starting from JSON instead of an array of objects, I built a free JSON ↔ CSV converter that handles both directions in the browser.

Tagged: Node.js · All topics
~~~

Related posts about node: