The first JSON-to-CSV converter I ever wrote lasted three days in production.
It was an "export to spreadsheet" button in a Laravel admin panel, and my conversion logic was — I'm not proud of this — values.join(","). It sailed through testing. Then a user exported a customer list where one company was named "Smith, Jones & Partners," and every column after it shifted one position to the right. Their accountant imported 340 rows of misaligned data before anyone noticed the phone numbers were in the email column.
The comma in CSV isn't a separator you can string-join your way around. It's a grammar, defined in RFC 4180, with actual escaping rules. That bug is why the JSON to CSV Converter I later built for toolz.dev treats escaping as non-negotiable — and why this guide spends real time on the edge cases, not just the happy path.
Here are the five methods I actually use, when each one wins, and where each one bites.
TL;DR: For one-off conversions, paste your JSON into the toolz.dev JSON to CSV Converter — it flattens nested objects with dot-notation, escapes correctly per RFC 4180, and runs 100% in your browser. For recurring jobs, script it:
pd.json_normalize()in Python or thejson2csvpackage in Node. Validate with the JSON Formatter first, and keep the original JSON — CSV flattening is one-way.
Why Do You Need CSV When You Already Have JSON?
Because the people who need your data don't live in your terminal. Every conversion request I've ever gotten reduces to one of five situations:
Analysts work in spreadsheets. Excel, Google Sheets, Tableau, Power BI — they all inhale CSV natively and choke on nested JSON. Converting API output to CSV is how engineering data reaches the business side.
Databases bulk-import flat files. PostgreSQL's COPY and MySQL's LOAD DATA want tabular input. JSON columns exist, but loading into real relational tables means flattening first.
Migrations need a lingua franca. Moving data between a NoSQL store and a relational one, or between two SaaS platforms, CSV is the format both ends reliably understand.
Compliance likes flat files. Some archival requirements specify human-readable formats. A CSV opens in anything, decades from now.
Stakeholders can't read JSON. A product manager asking "can I get that as a spreadsheet?" is the single most common trigger. It was the trigger for my broken export button.
What Makes JSON-to-CSV Conversion Hard?
Flat JSON is trivial. This:
[
{"id": 1, "name": "Alice", "email": "[email protected]", "age": 30},
{"id": 2, "name": "Bob", "email": "[email protected]", "age": 25}
]
becomes this, keys to headers, elements to rows:
id,name,email,age
1,Alice,[email protected],30
2,Bob,[email protected],25
But real API responses are never flat. They look like this:
[
{
"id": 1,
"name": "Alice",
"address": {"street": "123 Main St", "city": "San Francisco", "state": "CA"},
"skills": ["JavaScript", "Python", "Go"]
}
]
CSV has no concept of "inside." So you pick a flattening strategy, and each has a cost:
Dot-notation flattening — nested keys become compound headers:
id,name,address.street,address.city,address.state,skills
1,Alice,123 Main St,San Francisco,CA,"JavaScript; Python; Go"
Indexed columns for arrays — skills.0, skills.1, skills.2. Predictable, but a record with 14 skills produces 14 columns for everyone.
JSON-encoded cells — stuff the raw JSON into the cell, double-quoted. Lossless, unreadable, and it makes analysts sad.
Dot-notation with joined arrays is the right default for human consumption — it's what the toolz.dev converter produces. Indexed columns win when downstream code needs each element addressable. JSON-in-cells is a last resort for round-tripping.
Method 1: How Do You Convert JSON to CSV Online?
Best for: one-off conversions, non-developers, anything under a few dozen MB.
- Open the JSON to CSV Converter.
- Paste your JSON — an array of objects, or a single object.
- The tool detects the structure, flattens nested objects to dot-notation, and renders the CSV instantly.
- Copy it, or download the
.csv.
The reason I default to this over a script for anything non-recurring: zero setup, correct RFC 4180 escaping (learned that lesson), automatic key-union across inconsistent objects, and — because it's client-side — the API response full of customer emails you just pasted never leaves your machine. Watch the Network tab if you don't believe me; that's the test I apply to every online converter, and most fail it.
Where it's the wrong tool: recurring conversions (script it) and deeply pathological nesting where you'll want to hand-pick the flattening strategy.
Method 2: How Do You Convert JSON to CSV in JavaScript?
Best for: build pipelines, Node services, custom transformation logic.
Here's the minimal correct version — note the escaping, which is the part my three-day disaster skipped:
function jsonToCsv(jsonArray) {
if (!jsonArray.length) return "";
const headers = Object.keys(jsonArray[0]);
const csvRows = [
headers.join(","),
...jsonArray.map(row =>
headers.map(header => {
const value = row[header] ?? "";
// RFC 4180: double embedded quotes, wrap anything containing , " or newline
const escaped = String(value).replace(/"/g, '""');
return /[,"\n\r]/.test(escaped) ? `"${escaped}"` : escaped;
}).join(",")
)
];
return csvRows.join("\n");
}
For nested input, flatten first and union the keys — taking headers from only the first object is the second-most-common bug in hand-rolled converters:
function flattenObject(obj, prefix = "") {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value && typeof value === "object" && !Array.isArray(value)) {
Object.assign(result, flattenObject(value, newKey));
} else if (Array.isArray(value)) {
result[newKey] = value.join("; ");
} else {
result[newKey] = value;
}
}
return result;
}
function nestedJsonToCsv(jsonArray) {
const flattened = jsonArray.map(item => flattenObject(item));
// Union of ALL keys, not just the first object's
const headers = [...new Set(flattened.flatMap(Object.keys))];
// ...then emit rows exactly as in jsonToCsv above
}
Or skip the hand-rolling — the json2csv package has handled these edges for years:
import { Parser } from "json2csv";
const parser = new Parser({ flatten: true });
const csv = parser.parse(data);
Method 3: How Do You Convert JSON to CSV in Python?
Best for: data science workflows, anything already touching pandas.
The pandas one-liner covers flat JSON:
import pandas as pd
df = pd.read_json("data.json")
df.to_csv("output.csv", index=False)
The genuinely useful function is pd.json_normalize() — purpose-built for nested API responses:
import pandas as pd
import requests
response = requests.get("https://api.example.com/users")
df = pd.json_normalize(response.json())
print(df.columns.tolist())
# ['id', 'name', 'skills', 'address.street', 'address.city', 'address.state']
# Arrays still need a decision — join them explicitly:
df["skills"] = df["skills"].apply(lambda x: "; ".join(x) if isinstance(x, list) else x)
df.to_csv("output.csv", index=False)
Note that json_normalize flattens nested objects but leaves arrays as Python lists — if you skip the join step, your CSV cells contain ['JavaScript', 'Python'] verbatim. Everyone hits this once.
No pandas available? The standard library handles flat JSON fine:
import json, csv
with open("data.json") as f:
data = json.load(f)
with open("output.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
Method 4: How Do You Convert JSON to CSV From the Command Line?
Best for: shell scripts, CI pipelines, servers where installing pandas is overkill.
jq does it natively with @csv, which escapes correctly:
cat data.json | jq -r '
(.[0] | keys_unsorted) as $keys |
($keys | @csv),
(.[] | [.[$keys[]]] | @csv)
'
csvkit's in2csv is the low-thought option:
pip install csvkit
in2csv data.json > output.csv
And Miller (mlr) shines when you want filtering in the same pass:
mlr --json2csv filter '$age > 25' data.json > output.csv
The composability is the point — curl -s api.example.com/data | jq ... > report.csv is a complete API-to-spreadsheet pipeline in one line of cron.
Method 5: Can You Import JSON Directly Into Excel or Google Sheets?
Best for: non-developers, live-refreshing data, one-off imports.
Excel: Data → Get Data → From Web, paste the API URL, and Power Query gives you a visual editor to expand nested records before loading. Genuinely good for repeated refreshes of the same source.
Google Sheets: Extensions → Apps Script, then a small fetch function:
function importJSON(url) {
const response = UrlFetchApp.fetch(url);
const data = JSON.parse(response.getContentText());
if (!Array.isArray(data) || data.length === 0) return [["No data"]];
const headers = Object.keys(data[0]);
const rows = data.map(item => headers.map(h => item[h] ?? ""));
return [headers, ...rows];
}
Used in a cell as =importJSON("https://api.example.com/data").
Honest take: for one-off imports, converting with the online tool and opening the CSV is faster than either. The spreadsheet-native routes earn their setup cost only when the data refreshes on a schedule.
Which Method Should You Pick?
| Method | Setup | Nested JSON | Recurring use | Data stays local |
|---|---|---|---|---|
| Online converter | None | Automatic | Manual each time | Yes — client-side |
| JavaScript / json2csv | npm install | Via flatten |
Excellent | Yes |
| Python / pandas | pip install | json_normalize |
Excellent | Yes |
| jq / csvkit / mlr | Package manager | Manual paths | Excellent (cron/CI) | Yes |
| Excel / Sheets | Account/app | Power Query UI | Good (auto-refresh) | Excel: yes; Sheets: Google servers |
My rule: reach for the browser tool until the third time I'm converting the same shape of data — then it becomes a script.
What Edge Cases Break JSON-to-CSV Conversion?
Four traps account for nearly every broken export I've debugged:
Inconsistent keys. Object 1 has email, object 2 has phone, object 3 has both. Take headers from the first object only and you silently drop data. The fix is a key-union across all objects, with missing values as empty cells — which good tools do automatically.
Unescaped special characters. The "Smith, Jones & Partners" problem. Per RFC 4180: wrap values containing commas, quotes, or newlines in double quotes, and double any embedded quotes ("He said ""hello""").
Large files. Past 100 MB or so, whole-file parsing gets painful. Stream instead — jq streams, pandas reads in chunks, and JSON Lines format (one object per line) makes both easier. For files up to a few dozen MB, the browser tool is fine since there's no upload.
Encoding. Names and addresses carry non-ASCII characters. Keep everything UTF-8 end to end, and be suspicious of Excel on Windows, which historically wanted a BOM to detect UTF-8 correctly.
And one practice that isn't optional: validate before you convert. A truncated JSON file fails confusingly mid-conversion but obviously in the JSON Formatter. Thirty seconds of validation beats ten minutes of "why is my CSV empty."
Frequently Asked Questions
How do I convert JSON to CSV online for free?
Paste your JSON into the JSON to CSV Converter on toolz.dev — it instantly generates CSV with nested objects flattened and escaping handled, then lets you copy or download the result. No signup, and processing is 100% client-side, so your data never leaves your browser.
Can I convert nested JSON to CSV?
Yes. Nested objects flatten to dot-notation headers (address.city), and arrays are either joined into a delimited string or split into indexed columns. The toolz.dev converter applies dot-notation automatically; in Python, pd.json_normalize() does the same.
How do I convert a JSON file to CSV in Python?
import pandas as pd; pd.read_json("data.json").to_csv("output.csv", index=False) for flat JSON. For nested structures, use pd.json_normalize(data) first — and remember to join any array columns yourself, since normalize leaves lists intact.
What's the best way to convert very large JSON files?
Stream rather than load: jq on the command line, or pandas with chunked reads. Converting the file to JSON Lines (one object per line) first makes streaming much simpler. Browser tools are comfortable up to a few dozen MB; beyond ~100 MB, use the command line.
How do I convert CSV back to JSON?
The CSV to JSON Converter reverses the trip — each row becomes an object keyed by the header row. Programmatically: pd.read_csv("data.csv").to_json(orient="records").
Why does my CSV have quotes around some values?
That's correct behavior, not a bug. RFC 4180 requires double quotes around any value containing commas, newlines, or quote characters, with embedded quotes doubled. Spreadsheets and parsers strip them on read.
Is JSON-to-CSV conversion lossless?
For flat JSON, yes. For nested JSON, the values survive but the hierarchy doesn't — dot-notation headers are a flattened representation, and you can't always reconstruct the exact original nesting from them. Keep the source JSON; treat the CSV as a derived view.
Why are my columns misaligned after converting?
Almost always an escaping failure: a value containing a comma wasn't quoted, so parsers see extra columns from that point on. It's the exact bug from my Laravel export button. Use a converter that implements RFC 4180 rather than string-joining values — and if you wrote your own, test it with a value like Smith, Jones & Partners.
How do I convert JSON to CSV in Excel or Google Sheets?
Both apps import JSON through a helper rather than a paste. In Excel, use Data → Get Data → From File → From JSON, then flatten the query in Power Query and Close & Load. In Google Sheets, paste small arrays through a temporary Apps Script or convert with the JSON to CSV Converter first and open the resulting file — usually the faster path for a one-off.
Which JSON to CSV method should I use?
For a quick one-off, a client-side converter is fastest and keeps data private. For repeatable pipelines, use Python with pandas; for huge files, stream with jq on the command line; and reach for spreadsheet import only when non-developers own the workflow. Match the tool to how often you'll repeat the job, not to the file's size alone.
Match the Method to the Job
JSON-to-CSV looks like a solved one-liner until a comma in a company name shifts 340 rows of customer data one column to the right. The method matters less than respecting the format: escape per RFC 4180, union your keys, decide your flattening strategy on purpose, and keep the original JSON.
For the next one-off conversion, the JSON to CSV Converter is the fifteen-second path. Validate first with the JSON Formatter, and when the data needs to travel back, the CSV to JSON Converter closes the loop — all three in your browser, none of them ever seeing your data server-side.
Related Articles:

