Skip to content
jsoncsvonline

How to Convert JSON to CSV: The Complete Guide

Published

Convert JSON to CSV online or programmatically: flatten nested objects, handle arrays, map keys to columns, and export clean, spreadsheet-ready CSV tables.

Quick answer

To convert JSON to CSV, parse the JSON array, extract the union of all record keys to form the header row, flatten any nested objects into dot-separated column names (such as user.name), and format array values into columns or rows. You can convert files instantly with zero server uploads using our free online JSON to CSV converter, or run a lightweight script in Python or Node.js without third-party dependencies.


Realistic example

Consider this JSON array containing typical customer records with nested objects and varying keys:

[
  {
    "id": 101,
    "user": { "name": "Alice Chen", "city": "Seattle" },
    "role": "admin"
  },
  {
    "id": 102,
    "user": { "name": "Bob Taylor", "city": "Austin" },
    "verified": true
  }
]

Resulting CSV output

id,user.name,user.city,role,verified
101,Alice Chen,Seattle,admin,
102,Bob Taylor,Austin,,true

Notice that missing keys (such as verified in record 101, or role in record 102) produce empty fields without throwing errors, and nested objects flatten into distinct columns.


How JSON flattening works

JSON is a hierarchical tree structure, whereas CSV is a flat two-dimensional matrix (rows and columns). Transforming one to the other requires resolving three structural differences:

1. Key union for header generation

Because JSON objects in an array may have differing properties, a converter must inspect records to compile a complete header row containing every discovered field. When a record lacks a specific property, an empty field is output.

2. Dotted notation for nested objects

Nested properties like {"user": {"city": "Seattle"}} flatten into compound column names using a path delimiter. The default separator is a dot (user.name), but underscores (user_name) or slashes (user/name) can be selected if your database schema requires them.

3. Array handling strategies

Arrays within records cannot be converted into a single scalar value without making a deliberate choice:

  • One column per index: tags.0, tags.1 (preserves discrete items across columns).
  • One row per item (unwind): Duplicates parent scalar values across multiple rows (standard for relational database imports).
  • Joined cell: Concatenates values with a delimiter, e.g. "tag1; tag2" (compact, human-readable).
  • Raw JSON text: Keeps ["tag1", "tag2"] intact inside a single quoted CSV cell.

For deeper technical details on flattening rules, read our dedicated tutorial on flattening nested JSON into CSV columns.


Common conversion problems

  1. Excel delimiter issues: European versions of Excel split columns on semicolons (;) rather than commas. Use our Excel preset to emit semicolon-separated CSV with a Byte-Order Mark (BOM).
  2. Loss of precision on long numeric IDs: Large integers (like 18-digit Snowflake or Twitter IDs) are rounded by spreadsheet programs when treated as numbers. Exporting as text or using our JSON to Excel workbook converter preserves IDs as strings.
  3. Invalid JSON syntax: A missing closing bracket or trailing comma prevents parsing. Validate syntax first using the client-side JSON Validator.
  4. Memory exhaustion on massive files: Traditional tools crash when loading multi-gigabyte files. See our guide on handling very large JSON files for streaming strategies.

Programmatic conversion examples

Convert JSON to CSV in Python (pandas)

import json
import pandas as pd

with open("data.json", encoding="utf-8") as f:
    data = json.load(f)

# Flatten nested dictionaries automatically
df = pd.json_normalize(data)
df.to_csv("output.csv", index=False)

Convert JSON to CSV in Node.js (Standard Library)

import { readFile, writeFile } from 'node:fs/promises';

const data = JSON.parse(await readFile('data.json', 'utf8'));
const headers = [...new Set(data.flatMap(row => Object.keys(row)))];

const escapeField = (val) => {
  const str = val == null ? '' : String(val);
  return /[",\n]/.test(str) ? `"${str.replaceAll('"', '""')}"` : str;
};

const rows = [
  headers.join(','),
  ...data.map(row => headers.map(h => escapeField(row[h])).join(','))
];

await writeFile('output.csv', rows.join('\n'), 'utf8');