← Back to Nominal
Developer Guide

How to Convert Nested JSON to CSV

June 20, 2026 8 min read

Most JSON-to-CSV converters break the moment your data has nested objects or arrays. They either drop nested fields entirely, produce malformed CSV, or leave you writing custom parser code at 10pm. This guide shows you exactly how nested JSON to CSV conversion works, why standard tools fail, and how to handle it properly in JavaScript and Python — with working code you can copy today.

Why Nested JSON Breaks Standard Converters

CSV is a flat format. Each row is a single record. Each column is a top-level field. When your JSON has nested objects like {"user": {"name": "Alice", "city": "Berlin"}}, a naive converter has two choices: skip the nested data, or produce garbage output. Neither is acceptable.

The problem is that CSV has no native concept of hierarchy. You have to decide how to represent nested data as flat columns. The three common strategies:

Nominal's converter uses dot notation for objects and handles arrays with a configurable strategy. Let's walk through how it works.

Step-by-Step: Flattening Nested JSON in JavaScript

The core operation is a recursive flatten — traverse every level of nesting and build dot-notation keys. Here's a clean implementation:

javascript — flattenNested.js
function flattenNested(obj, prefix = '') {
  const result = {};

  for (const [key, value] of Object.entries(obj)) {
    const newKey = prefix ? `${prefix}.${key}` : key;

    if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
      const nested = flattenNested(value, newKey);
      Object.assign(result, nested);
    } else {
      result[newKey] = value;
    }
  }

  return result;
}

Apply it to a real data structure:

javascript — example
const data = {
  orderId: 'ORD-8821',
  customer: {
    name: 'Alice Chen',
    tier: 'premium'
  },
  items: [
    { sku: 'WIDGET-A', qty: 3, price: 12.99 },
    { sku: 'GADGET-B', qty: 1, price: 49.99 }
  ],
  shipping: { city: 'Berlin', country: 'DE' }
};

console.log(flattenNested(data));
// {
//   orderId: 'ORD-8821',
//   'customer.name': 'Alice Chen',
//   'customer.tier': 'premium',
//   'items': '[{"sku":"WIDGET-A","qty":3,"price":12.99},{"sku":"GADGET-B","qty":1,"price":49.99}]',
//   'shipping.city': 'Berlin',
//   'shipping.country': 'DE'
// }
Note on arrays: The flatten above serializes arrays as JSON strings, which keeps every record on one row. If you need one row per array element (expanding arrays), that's a separate pre-processing step covered in the Python section below.

Converting the Result to CSV

With a flat object in hand, generating CSV is straightforward:

javascript — toCSV.js
function toCSV(rows) {
  if (!rows.length) return '';

  const headers = Object.keys(rows[0]);
  const escape = v => `"${String(v ?? '').replace('"', '""')}"`;

  const headerRow = headers.map(escape).join(',');
  const dataRows = rows.map(r => headers.map(h => escape(r[h])).join(','));

  return [headerRow, ...dataRows].join('\n');
}

Python Alternative: Using Pandas

If you're working in Python, pandas.json_normalize handles nested flattening in one call:

python — nested_to_csv.py
import json
import pandas as pd

with open('data.json') as f:
    data = json.load(f)

# Expand arrays into multiple rows (record_path) — one row per item
df = pd.json_normalize(
    data,
    record_path='items',   # array to expand
    meta=['orderId', ['customer', 'name']],  # fields to carry over
    sep='.'
)

df.to_csv('output.csv', index=False)

# Output columns:
# orderId | customer.name | sku | qty | price

For objects nested inside arrays, use the meta parameter to pull in parent-level fields at the row level. The sep='.' option gives you dot-notation column headers to match the JavaScript behavior above.

Common Edge Cases and How to Handle Them

Quick Reference
  • Null values: Represent as empty CSV cells — not the string "null"
  • Booleans: Serialize as lowercase true/false
  • Deeply nested objects: Path depth has no limit — dot notation handles any depth
  • Mixed types: If a key is a string in one record and an object in another, coerce to string
  • CSV with commas in values: Always quote fields that contain commas, quotes, or newlines

Handling Arrays Without Dropping Data

The most common mistake: serializing an array as its .toString() output, which gives you "item1,item2,item3" — useless for downstream processing. Instead, decide upfront:

Try It Live

If you'd rather not write the code yourself, Nominal's converter handles nested JSON to CSV automatically — client-side, no upload required, free for 2 conversions per day.

Nested JSON → CSV in seconds

No signup. No data sent to a server. Runs entirely in your browser.

Open Converter →

When to Write Code vs. Use a Tool

If you need to convert nested JSON to CSV once, use a tool. If you need to do it regularly as part of a pipeline, write the code — the flatten function above is 30 lines and handles 95% of real-world cases.

The one scenario where code is strictly better: when you need to handle schema changes gracefully. A pipeline that rebuilds its column map from the actual keys in each input will never break on new fields, while a static converter that hardcodes column names will silently drop new data.

For occasional one-off conversions, a tool with dot-notation flattening is faster and less error-prone than writing and debugging a parser.

Summary

Nested JSON to CSV conversion requires two steps: flatten the nested structure into dot-notation keys, then emit those keys as CSV columns. The flattening step is where most tools fail — not the CSV generation.

For JavaScript, a recursive flattenNested function handles any depth of nesting. For Python, pandas.json_normalize does it in one call. For quick one-off conversions, Nominal's converter is already built and free to use.