How the JSON to CSV converter works
The input is parsed with JSON.parse, then turned into rows depending on its shape:
- An array of objects gives one row per object. This is the usual shape of an API list endpoint or a database export.
- A single object gives one row.
- An array of arrays is written row by row exactly as it is, so the first inner array acts as the header if you put one there.
- An array of plain values such as
[1, "two", true] gives a single column named value.
A lone number or string is rejected. For objects, the columns are every key found in any row, in the order first seen. Missing keys and null give empty cells. Cells containing the delimiter, a double quote, or a line break are quoted, with inner quotes doubled, and rows end with CRLF as RFC 4180 specifies. Download saves data.csv.
Example: exporting orders with nested customers
[
{
"id": 1001,
"customer": { "name": "Ada Lovelace", "email": "[email protected]",
"address": { "city": "London", "zip": "N1 9GU" } },
"items": [ { "sku": "KB-01", "qty": 1 }, { "sku": "MS-02", "qty": 2 } ],
"total": 149.5,
"paid": true,
"note": null
},
{
"id": 1002,
"customer": { "name": "Grace Hopper, PhD", "email": "[email protected]",
"address": { "city": "Arlington" } },
"items": [],
"total": 42,
"paid": false,
"note": "Leave at \"front desk\"",
"coupon": "SPRING"
}
]
With the default settings (comma, header row, flatten objects) the output is:
id,customer.name,customer.email,customer.address.city,customer.address.zip,items,total,paid,note,coupon
1001,Ada Lovelace,[email protected],London,N1 9GU,"[{""sku"":""KB-01"",""qty"":1},{""sku"":""MS-02"",""qty"":2}]",149.5,true,,
1002,"Grace Hopper, PhD",[email protected],Arlington,,[],42,false,"Leave at ""front desk""",SPRING
The nested address became dot-notation columns, the missing zip and coupon left empty cells, the name with a comma is quoted, and items stayed as JSON text in one cell.
How nested data maps to columns
Nested objects
With Flatten objects on, nested keys become dot-joined columns. With it off, the whole object is written as JSON text in one cell, useful when the target system parses that column itself.
Arrays inside records
Arrays are never expanded into more rows or into numbered columns. If you need one row per order line, reshape the data first. In a browser console or Node.js:
const rows = orders.flatMap(o =>
o.items.map(item => ({ order_id: o.id, ...item }))
);
console.log(JSON.stringify(rows));
Paste the printed array into the converter and each item becomes its own row.
Two quirks to watch
- An empty nested object, such as
"meta": {}, produces no column at all.
- A literal key that contains a dot collides with a flattened one. In
{"a.b": 1, "a": {"b": 2}} both map to the column a.b, and the later value (2) silently wins.
Problems when you open the CSV
- Only one row. Most APIs wrap records:
{"data": [...], "meta": {...}}. A top-level object becomes one row, so paste just the data array.
- Garbled accents in Excel. The file is UTF-8 without a byte order mark. Excel on Windows may show
café as café when opened by double-click. Use Data, From Text/CSV and pick UTF-8.
- Everything in column A. Excel in locales that use a decimal comma expects semicolons. Choose Delimiter: Semicolon. Decimal numbers are still written with a dot (
149.5), so check that column after import.
- Lost leading zeros. The CSV contains
02134, but spreadsheets convert it to 2134. Import such columns as text.
- Values starting with
=, +, - or @ are written unchanged and a spreadsheet may run them as formulas. If the data comes from untrusted users, clean those cells before sharing the file.
- Header row seems ignored. The checkbox only applies to arrays of objects. Arrays of arrays are output as they are.
- Error on mixed rows. If the first element is an array and later ones are objects, conversion fails. Keep every row the same shape.
When to use a different tool
- To go the other way, use CSV to JSON.
- To inspect a large payload and find the array you need, pretty-print it with the JSON Formatter.
- If the input is rejected as invalid, try the JSON Repair tool.
- To publish a small data set on a web page rather than in a spreadsheet, build it with the HTML Table Generator.
Frequently asked questions
How are nested JSON objects converted to CSV columns?
With Flatten objects enabled (the default), each nested key becomes its own column named with dot notation, so {"customer": {"address": {"city": "London"}}} produces a column called customer.address.city. With Flatten objects turned off, the whole nested object is written as JSON text in a single cell.
What happens to arrays inside my JSON?
Arrays are written as JSON text in one cell, for example [{"sku":"KB-01","qty":1}]. They are not split into extra rows or numbered columns. If you need one row per array item, reshape the data first so that each item is its own object in the top-level array.
Why does Excel show strange characters like é in my CSV?
The downloaded file is UTF-8 without a byte order mark, and Excel on Windows often assumes an older encoding when it opens such a file by double-click. Import it instead through Data, From Text/CSV, and choose UTF-8 as the file origin. Google Sheets reads the file correctly as it is.
Which delimiter should I choose?
Use comma for most tools and for English-language Excel. Use semicolon if your Excel uses a comma as the decimal separator, which is common in much of Europe. Tab is handy for pasting into a spreadsheet or for data that contains many commas. Pipe suits some database import tools.
Why is my CSV only one row?
Your JSON is probably a single object that wraps the records, such as {"data": [...], "meta": {...}}. The tool turns a top-level object into one row, so the records end up as JSON text in a data column. Paste only the array of records instead.
Is my data uploaded?
No. Parsing and conversion run in your browser, and the CSV file is created locally when you click Download. Import URL fetches the file directly from your browser.