JSON-to-CSV is one of the most common data conversions: APIs return JSON, but spreadsheets and BI tools want CSV. The conversion is easy when your JSON is a flat array of objects — and tricky when it isn't. Here are five approaches with their trade-offs.
The easy case: flat array of objects
Most JSON-to-CSV converters expect input in this shape:
[
{"name": "Alice", "age": 30, "role": "admin"},
{"name": "Bob", "age": 25, "role": "user"}
]
The mapping is obvious: each object becomes a row, each key becomes a column header. If your JSON already looks like this, any tool works.
Method 1: online converter
For one-off conversions, our JSON to CSV converter handles the flat case in two clicks and lets you pick the delimiter (comma, tab, semicolon). It also handles arrays of unequal-shaped objects by union-ing the keys.
Method 2: Python with pandas
For programmatic conversion, pandas is the workhorse:
import pandas as pd, json
with open('data.json') as f:
data = json.load(f)
df = pd.DataFrame(data)
df.to_csv('out.csv', index=False)
If your JSON has nested objects, use json_normalize to flatten them:
df = pd.json_normalize(data, sep='_')
# nested.address.city becomes "address_city"
For arrays nested in records (one record has many tags, say), json_normalize can expand them with the record_path argument — though at some point you're better off thinking about whether one row per record really makes sense.
Method 3: jq for command-line
If you live in the shell, jq converts JSON to CSV in one pipeline:
cat data.json | jq -r '
(.[0] | keys_unsorted) as $keys |
$keys, (.[] | [.[$keys[]]])
| @csv
' > out.csv
What's happening: (.[0] | keys_unsorted) grabs the headers from the first object. The next line emits each row as an array, in header order. @csv handles quoting and escaping properly (quotes inside fields become "", fields with commas get wrapped). This is the fastest method for huge files because jq streams.
Method 4: Node.js with json2csv
npm install @json2csv/plainjs
import { Parser } from '@json2csv/plainjs';
const parser = new Parser({ fields: ['name', 'age', 'role'] });
const csv = parser.parse(data);
Specifying fields explicitly gives you control over column order and which keys are included — useful when the JSON has more keys than you want exported.
Method 5: PowerShell (Windows)
Get-Content data.json | ConvertFrom-Json | Export-Csv out.csv -NoTypeInformation
Built-in, no dependencies. Surprisingly capable for sysadmin scripts.
The hard case: nested data
Real JSON often has nested arrays and objects. There's no canonical way to represent that in CSV — you have to pick a strategy:
Flatten with dot-paths. {"user": {"name": "A"}} becomes a column called user.name. Works when the nesting is shallow and uniform. Breaks for arrays of objects.
One row per leaf. Duplicate parent fields across rows. {"order": "X", "items": [{"sku": "A"}, {"sku": "B"}]} becomes two rows: X, A and X, B. This is what database OLAP tools do.
JSON-in-a-cell. Serialize the nested structure as a JSON string in one cell. Preserves data, but spreadsheets can't query it.
Whichever you pick, document it. The next person looking at the CSV won't be able to reverse-engineer your choice.
CSV quoting rules to know
The CSV spec (RFC 4180) requires: fields containing commas, double-quotes, or line breaks must be enclosed in double quotes; literal double-quotes inside a quoted field are doubled (""). Every tool above handles this. Don't try to write your own CSV serializer with string concatenation — you will get the edge cases wrong.
Wrap-up
For one-time conversions, the online tool is fastest. For automation, pick the tool that matches your stack: pandas for data work, jq for scripts, json2csv for Node services. Reach for explicit flattening rules whenever your JSON has nesting deeper than one level.