Conversion 7 min read January 24, 2026

How to Convert JSON to CSV Without Losing Nested Data

A practical guide to converting nested JSON to CSV, covering flattening strategies, JavaScript code examples, library options, and how to handle arrays of objects.

JSON is hierarchical: it can nest objects inside objects, arrays inside arrays, many levels deep. CSV is flat, a grid of rows and columns. Converting between them is non-trivial, and naive approaches silently discard nested data. This guide explains how to do it correctly.

Why JSON-to-CSV Conversion Is Non-Trivial

A simple array of flat objects converts to CSV almost directly. But real-world JSON almost always contains nested structures:

json
[
  {
    "id": 1,
    "name": "Alice",
    "address": {
      "city": "San Francisco",
      "state": "CA"
    },
    "tags": ["developer", "admin"]
  }
]

The `address` object and `tags` array cannot fit directly into a flat CSV row. You must decide how to represent them, and the wrong choice means silently losing data.

Strategy 1: Dot-Notation Flattening

The most common and lossless approach for nested objects is to flatten keys using dot notation. The nested structure becomes part of the column name:

text
id,name,address.city,address.state,tags
1,Alice,San Francisco,CA,"[""developer"",""admin""]"

This is lossless for objects and keeps the CSV importable. Arrays are serialized as a JSON string within the cell (not ideal for spreadsheets, but it preserves all data).

Strategy 2: Array Expansion (One Row Per Item)

When an array contains objects (common in API responses), you can expand it so each array item becomes its own row:

json
[
  {
    "orderId": "A001",
    "items": [
      { "sku": "X1", "qty": 2 },
      { "sku": "Y9", "qty": 1 }
    ]
  }
]

Expanded output (the orderId is duplicated for each item row):

text
orderId,items.sku,items.qty
A001,X1,2
A001,Y9,1

Strategy 3: Join Arrays as Strings

For arrays of primitive values (strings, numbers), joining them into a delimited string is simple and readable:

text
id,name,tags
1,Alice,"developer|admin"

💡 Tip

Avoid commas as array delimiters within CSV cells since they conflict with CSV field separation. Use `|`, `;`, or serialize as a JSON array string instead.

Writing a Flattener in JavaScript

javascript
function flattenObject(obj, prefix = '') {
  return Object.keys(obj).reduce((acc, key) => {
    const fullKey = prefix ? `${prefix}.${key}` : key;
    const value = obj[key];

    if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
      // Recurse into nested objects
      Object.assign(acc, flattenObject(value, fullKey));
    } else if (Array.isArray(value)) {
      // Serialize arrays as JSON strings
      acc[fullKey] = JSON.stringify(value);
    } else {
      acc[fullKey] = value;
    }
    return acc;
  }, {});
}

// Convert array of JSON objects to CSV string
function jsonToCsv(jsonArray) {
  const flat = jsonArray.map(row => flattenObject(row));
  const headers = [...new Set(flat.flatMap(Object.keys))];
  const rows = flat.map(row =>
    headers.map(h => {
      const val = row[h] ?? '';
      // Escape values containing commas or quotes
      return typeof val === 'string' && (val.includes(',') || val.includes('"'))
        ? `"${val.replace(/"/g, '""')}"`
        : val;
    }).join(',')
  );
  return [headers.join(','), ...rows].join('\n');
}

Don't want to write the code yourself?

Our JSON to CSV converter does all of this automatically. Paste your JSON and get a properly flattened CSV file with dot-notation headers.

Try JSON to CSV

Using Libraries

Several well-maintained npm packages handle JSON-to-CSV conversion with more options than a hand-rolled solution:

  • json2csv: The most popular option. Supports nested flattening, custom headers, transforms, and streaming large datasets. Install: `npm install json2csv`.
  • Papa Parse: Primarily a CSV parser, but also supports JSON-to-CSV conversion with excellent browser compatibility. Zero dependencies.
  • flat: A utility package that just does object flattening (dot notation). Useful when you want to control CSV generation separately.

Edge Cases to Watch For

  • Inconsistent schemas: If not all JSON objects have the same keys, your CSV headers must be the union of all keys, with empty cells for missing values.
  • Deeply nested objects (3+ levels): Column names like `user.address.geo.lat` become unwieldy but remain valid.
  • Null values: Represent as empty string in CSV, not the string `null`.
  • Unicode and special characters: Ensure your CSV writer uses UTF-8 encoding, especially for names with accents or CJK characters.
  • Boolean values: CSV has no boolean type; use `true`/`false` strings or `1`/`0` depending on your target system.
  • Large numbers: JavaScript's `Number` type loses precision beyond 2^53. Use strings for large IDs (e.g., Twitter snowflake IDs).

Convert JSON to CSV in Seconds

Our JSON to CSV converter handles nested objects with dot-notation column headers. Paste your JSON and download a clean CSV instantly.

Open JSON to CSV Converter

Related Articles