npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

json-csv-kit

v0.1.1

Published

Convert JSON records to clean CSV with TypeScript-first options.

Readme

json-csv-kit

CI

Convert JSON records to clean CSV with TypeScript-first options.

json-csv-kit is a small utility for exports, admin tools, reports, support dashboards, docs generators and browser-based data tools. It keeps the common JSON-to-CSV path simple while leaving room for explicit columns, nested data and safe CSV escaping.

Demo: packages.wasta-wocket.fr/json-csv-kit/

Package quality

  • TypeScript types are generated from the source.
  • ESM-only package with no runtime dependencies.
  • Marked as side-effect free for bundlers.
  • Tested on Node.js 20 and 22 with GitHub Actions.
  • Works in Node.js, browsers, Vite apps and static docs tooling.

Install

npm install json-csv-kit

json-csv-kit is ESM-only and targets Node.js 20 or newer. It also works in browsers through modern bundlers such as Vite, Rollup, webpack and esbuild.

Quick Start

import { jsonToCsv } from 'json-csv-kit';

const csv = jsonToCsv([
  { name: 'Ada', role: 'Engineer' },
  { name: 'Grace', role: 'Admiral' }
]);

console.log(csv);
name,role
Ada,Engineer
Grace,Admiral

Nested plain objects are flattened by default:

jsonToCsv([
  {
    customer: {
      name: 'Northwind',
      region: 'EU'
    },
    total: 120
  }
]);
customer.name,customer.region,total
Northwind,EU,120

Column order is based on the first time each key is discovered while reading your records. Use columns when you need a stable public export format.

Which API should I use?

| Function | Use it when you need | | --- | --- | | jsonToCsv | convert an array of records to a CSV string | | toCsv | short alias for jsonToCsv | | inferCsvColumns | inspect the columns that would be generated | | flattenRecord | flatten one nested object into dot-path keys | | escapeCsvCell | escape a single cell before composing CSV yourself |

Explicit columns

Use explicit columns when you need stable order, custom headers or a subset of fields.

jsonToCsv(rows, {
  columns: [
    { key: 'customer', header: 'Customer', path: 'customer.name' },
    { key: 'region', header: 'Region', path: 'customer.region' },
    { key: 'total', header: 'Total' }
  ]
});

Use an accessor for custom logic or when paths need bracket notation:

jsonToCsv(rows, {
  columns: [
    {
      key: 'city',
      header: 'City',
      accessor: (row) => row.customer?.['billing.address']?.city
    }
  ]
});

Format a column before CSV escaping:

jsonToCsv(rows, {
  columns: [
    {
      key: 'total',
      accessor: (row) => row.totalCents,
      formatter: (value) => `$${Number(value) / 100}`
    }
  ]
});

The generic API accepts normal TypeScript interfaces; your row type does not need an index signature.

interface Order {
  customer: {
    name: string;
  };
  totalCents: number;
}

const orders: Order[] = [
  { customer: { name: 'Ada' }, totalCents: 1234 }
];

const csv = jsonToCsv(orders, {
  columns: [
    { key: 'customer', path: 'customer.name' },
    {
      key: 'total',
      accessor: (row) => row.totalCents,
      formatter: (value) => `$${Number(value) / 100}`
    }
  ]
});

Browser download

The package returns a string, so you can decide how to save or upload it.

import { jsonToCsv } from 'json-csv-kit';

const csv = jsonToCsv(rows);
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
const url = URL.createObjectURL(blob);

const link = document.createElement('a');
link.href = url;
link.download = 'export.csv';
link.click();

URL.revokeObjectURL(url);

Nested data and paths

With inferred columns, nested plain objects are flattened into dot-path keys. Arrays, dates and other non-plain values stay as values.

jsonToCsv([{ user: { name: 'Ada' }, tags: ['admin', 'ops'] }]);
user.name,tags
Ada,"[""admin"",""ops""]"

If a source object has a real key containing dots, direct keys are checked before dot-path traversal:

jsonToCsv([{ 'user.name': 'Ada' }]);

Use accessor when your source needs bracket notation, computed values or more control than simple dot paths.

CSV safety

Values are escaped according to normal CSV rules:

  • fields containing the delimiter are quoted
  • fields containing newlines are quoted
  • quotes inside quoted fields are doubled
jsonToCsv([{ name: 'Ada, Lovelace', note: 'Line 1\n"Line 2"' }]);
name,note
"Ada, Lovelace","Line 1
""Line 2"""

When exporting to spreadsheets, use escapeFormulae to reduce formula-injection risk. Values that start with a formula marker, even after leading whitespace, are prefixed before CSV escaping:

jsonToCsv([{ value: '=SUM(A1:A2)' }], {
  escapeFormulae: true
});
value
'=SUM(A1:A2)

Use bom: true when a spreadsheet app needs the UTF-8 byte order mark to detect accented characters correctly.

Options

interface JsonToCsvOptions<TRecord> {
  columns?: Array<string | CsvColumn<TRecord>>;
  includeHeaders?: boolean;
  flatten?: boolean;
  sortColumns?: boolean;
  delimiter?: string;
  newline?: string;
  quote?: string;
  nullValue?: string;
  arrayMode?: 'json' | 'join' | 'empty';
  arraySeparator?: string;
  escapeFormulae?: boolean | string;
  bom?: boolean;
  dateFormatter?: (date: Date) => string;
}

| Option | Default | Meaning | | --- | --- | --- | | columns | inferred | explicit column list | | includeHeaders | true | include the first header row | | flatten | true | flatten nested plain objects into dot paths | | sortColumns | false | sort inferred columns alphabetically | | delimiter | ',' | field delimiter | | newline | '\n' | line separator | | quote | '"' | quote character | | nullValue | '' | output for null and undefined | | arrayMode | 'json' | format arrays as JSON, joined text or empty | | arraySeparator | ', ' | separator used by arrayMode: 'join' | | escapeFormulae | false | prefix spreadsheet-like formulas | | bom | false | prefix the output with a UTF-8 BOM for spreadsheet apps | | dateFormatter | ISO string | format Date values |

Arrays, dates and null values

Arrays are serialized as JSON by default because that preserves the original data most safely:

jsonToCsv([{ tags: ['admin', 'ops'] }]);

Use arrayMode: 'join' for human-readable lists, or arrayMode: 'empty' when arrays should be skipped:

jsonToCsv([{ tags: ['admin', 'ops'] }], {
  arrayMode: 'join',
  arraySeparator: ' | '
});

null and undefined are exported as an empty string by default. Use nullValue when your downstream tool needs an explicit marker:

jsonToCsv([{ name: 'Ada', team: null }], {
  nullValue: 'NULL'
});

Dates use toISOString() by default. Use dateFormatter for another format.

Ecosystem recipes

Use with object-key-paths to inspect columns before exporting:

import { getLeafPaths } from 'object-key-paths';
import { jsonToCsv } from 'json-csv-kit';

const columns = getLeafPaths(report).map((path) => ({
  key: path,
  header: path
}));

const csv = jsonToCsv([report], { columns });

Use with object-path-kit when source paths need bracket notation:

import { getPath } from 'object-path-kit';
import { jsonToCsv } from 'json-csv-kit';

const csv = jsonToCsv(rows, {
  columns: [
    {
      key: 'city',
      header: 'City',
      accessor: (row) => getPath(row, 'customer["billing.address"].city')
    }
  ]
});

Use with array-table-kit when you need both Markdown and CSV exports from the same records:

import { arrayToMarkdownTable } from 'array-table-kit';
import { jsonToCsv } from 'json-csv-kit';

const markdown = arrayToMarkdownTable(rows);
const csv = jsonToCsv(rows);

Notes

  • Input must be an array of plain objects.
  • Dot paths are intentionally simple. Use accessor or object-path-kit for bracket notation, ambiguous paths or computed values.
  • Arrays are serialized as JSON by default so no information is lost.
  • BigInt values inside arrays or objects are converted to strings during JSON serialization.
  • Circular references are represented as [Circular] instead of crashing the export.
  • Class instances, Map, Set and other non-plain objects are serialized as JSON when possible.

License

MPL-2.0