@iwsio/json-csv-node
Version:
ESM/CJS module that easily converts JSON to CSV. This package supports streaming and buffered conversion to CSV.
178 lines (150 loc) • 4.92 kB
Markdown
# /json-csv-node
[](https://github.com/iwsllc/json-csv/actions/workflows/push-node.yml)
This package extends [/json-csv-core](https://www.npmjs.com/package/@iwsio/json-csv-core) specifically targeting Node.JS to support streaming. This package now supports both ESM and CommonJS and includes the same API as `json-csv`. You can [read more about it on my blog.](https://iws.io/2023/json-csv-v6)
# Usage
## Buffered (Converts to CSV with an in-memory data source)
```js
const { toCsv, toCsvSync } = require('/json-csv-node') // CJS
import { toCsv, toCsvSync } from '/json-csv-node' // ESM
// as a promise
const csv = await toCsv(data, options) // toCsv returns Promise<string>
// optionally, you can use a classic callback instead
toCsv(data, options, function(err, csv) {...}))
// synchronous
const csv = toCsvSync(data, options) // toCsvSync returns string
```
## Streaming (Converts a "row at a time" from a stream source)
When using the streaming API, you can pipe data to it in object mode.
```js
const { toCsvStream } = require('/json-csv-node') // CJS
import { toCsvStream } from '/json-csv-node' // ESM
const things = [
{name: 'thing1', age: 20},
{name: 'thing2', age: 30},
{name: 'thing3', age: 45}
]
Readable.from(things) // <readable source in object mode>
.pipe(toCsvStream(options)) // transforms to string and emits lines
.pipe(process.stdout) // anything Writable
// toCsvStream(options) supports classic callback (for backwards compatibility)
toCsvStream(options, (err, transform) => {
Readable.from(things)
.pipe(toCsvStream(options))
})
```
### NOTE: All the aliases from previous versions remain intact.
I renamed this API mostly for cosmetics and to cleanup named exports for ES Modules. It made more sense to me to `import { toCSV } from 'json-csv'` rather than importing the default and calling its prop. (I've been doing a lot of Typescript lately). But all the original versions are kept intact and tests are in place to assert they work.
```js
const jsonCsv = require('/json-csv-node') // CJS
import jsonCsv, { toCSV, toCsvStream, buffered, stream } from '/json-csv-node' // ESM
jsonCsv.buffered // buffered (promise or callback)
jsonCsv.bufferedSync // buffered synchronous (passthrough from core)
jsonCsv.stream // stream (or callback w/ stream)
jsonCsv.toCsv // buffered, returns promise, callback optional
jsonCsv.toCsvSync // buffered synchronous (passthrough from core)
jsonCsv.toCsvStream // stream, returns stream, callback optional
// These are deprecated
jsonCsv.csv // alias to toCsvStream (streamed)
jsonCsv.csvBuffered // alias to toCsv (buffered)
```
## Options
```js
{
// field definitions for CSV export
fields :
[
{
// required: field name for source value
name: 'string',
// optional: column label for CSV header
label: 'string',
// optional: transform value before exporting
transform: function(value) { return value; }
}
],
// Other default options:
fieldSeparator: ",",
ignoreHeader: false
}
```
## Advanced Example
Here, you can see we're using a deeper set of objects for our source data, and we're using dot notation in the field definitions like: `contact.name` for the contact name.
```javascript
const items = [
{
downloaded: false,
contact: {
company: 'Widgets, LLC',
name: 'John Doe',
email: 'john .somewhere',
},
registration: {
year: 2013,
level: 3,
},
},
{
downloaded: true,
contact: {
company: 'Sprockets, LLC',
name: 'Jane Doe',
email: 'jane .somewhere',
},
registration: {
year: 2013,
level: 2,
},
},
]
const options = {
fields: [
{
name: 'contact.company', // uses dot notation
label: 'Company',
},
{
name: 'contact.name',
label: 'Name',
},
{
name: 'contact.email',
label: 'Email',
},
{
name: 'downloaded',
label: "Downloaded",
transform: (v) => v ? 'downloaded' : 'pending',
},
{
name: 'registration.year',
label: 'Year',
},
{
name: 'registration.level',
label: 'Level',
transform: (v) => {
switch (v) {
case 1: return 'Test 1'
case 2: return 'Test 2'
default: return 'Unknown'
}
},
},
],
}
(async () => {
let result = await toCsv(items, options)
console.log(result)
})()
// OR synchronous
(() => {
let result = toCsvSync(items, options)
console.log(result)
})()
```
### Output
```
Company,Name,Email,Downloaded,Year,Level
"Widgets, LLC",John Doe,john .somewhere,pending,2013,Unknown
"Sprockets, LLC",Jane Doe,jane .somewhere,downloaded,2013,Test 2
```