Home · Free tools · JSON to CSV

JSON to CSV

Paste JSON, or drop a .json file, and get a table back — then download it as CSV or .xlsx. It handles the shapes real exports come in: records wrapped in a data key, nested objects, records that do not all carry the same fields, and NDJSON with one JSON value per line. The file is read in this tab and is never uploaded.

Or drop a .json file

Drop .json or .ndjson here to load it into the box below

JSON paste it here, or edit what the file loaded

Nothing is uploaded. The file is read by JavaScript in this tab and never leaves your computer — no server sees it, and closing the tab throws it away.

How to convert JSON to CSV

  1. Paste or drop the JSON. A pasted response, a .json file or NDJSON with one object per line all work. Nothing is sent anywhere.
  2. Check which array it read. For a wrapped response the key it used is printed above the table — data, results, items, whatever your API calls it.
  3. Read the columns. Nested values become dotted columns like customer.name; a list of strings becomes one cell joined with semicolons.
  4. Download. CSV for a script or a database import, .xlsx if the next step is a spreadsheet.

Why most JSON does not convert cleanly

A CSV is a rectangle: a fixed set of columns, one row per record. JSON is a tree. Three differences account for nearly every failed conversion, and all three are decided before a single row is written.

  • The records are not at the top level. An API returns {"data": [ … ]}, {"results": [ … ]} or a paginated envelope with the rows one key down. Converting the envelope gives you one very wide row instead of many. This page looks for the first array of objects among the top-level keys and tells you which one it used.
  • Values are nested. {"customer": {"name": "Ada", "country": "GB"}} has to become two columns, customer.name and customer.country — not one cell reading [object Object]. Lists of plain values join into one cell; lists of objects get indexed columns (items.0.sku), which keeps them addressable instead of collapsing them.
  • The records disagree about their fields. Record three has a tags key the first two do not. The column set is the union of every record's keys, in the order they first appear, and missing values are written as empty cells — so nothing shifts left into the wrong column.

NDJSON is recognised too

Log files, BigQuery extracts and streaming exports are usually newline-delimited JSON: one complete JSON value per line, with no enclosing array and no commas between lines. That is not valid JSON as a whole document, so a strict parser rejects the file. If the paste fails to parse as one document, each line is parsed on its own before anything is reported as broken.

When the JSON is bad

A parse error says what the parser said and where — a trailing comma, a single quote, an unescaped newline inside a string. That is more useful than "invalid JSON", because those four are almost always what it is.

Converting the same export every week

A browser tab is the right tool the first two or three times. When the same endpoint has to land in the same sheet on a schedule, and somebody has to notice when a field disappears, the work is no longer a conversion.

TableDI 2 is a desktop app for file work you redo every period: it keeps your sources, rules and delivery as a job, so next month you drop in the new files and run it again. Everything runs on your own machine.

Questions people ask

My JSON is an object, not an array. Will it still convert?

Yes. A real API response is usually {"data": [ … ]} or {"results": [ … ]} — the records are one level down. The converter looks through the top-level keys for the first array whose items are objects and uses that, and it prints which key it read above the table so you can check it picked the right one. If there is no array at all, the object is treated as a single record and you get one row.

How are nested objects handled?

They become dotted columns. {"user":{"id":7,"name":"Ada"}} gives you user.id and user.name. Depth is not limited — a three-level path becomes a.b.c.

What happens to arrays inside a record?

An array of plain values — ["net30","eu"] — is joined into one cell as net30; eu, because those are usually tags and splitting them into columns makes the table ragged. An array of objects is expanded with its index in the column name, so items.0.sku and items.1.sku stay separate cells.

Does it accept NDJSON or a JSON Lines file?

Yes. If the whole paste is not valid JSON, each non-empty line is parsed as its own JSON value; if that works, they are treated as the records. The result says NDJSON above the table so you know which path it took.

Are my files uploaded anywhere?

No. The file is read by JavaScript running in this tab, using the browser's own DecompressionStream to unzip .xlsx and a parser that runs on your machine. There is no server call in the page — you can watch the network tab while you use it. Close the tab and the data is gone.

Is there a size limit?

No fixed limit — the ceiling is your browser tab's memory, and the preview shows the first 200 rows while the download has all of them. A few tens of megabytes of JSON is fine on a normal laptop; a file much larger than that is better handled by a script than by any browser tool, including this one.

Can I get Excel instead of CSV?

Yes — the .xlsx download writes the same table as a real spreadsheet file, which avoids the double-conversion where Excel reinterprets a CSV's dates and long numbers on open. There is also a dedicated JSON to Excel page.

Doing this every month?

TableDI 2 keeps it as a job — the files, the key columns, the tolerance and the fixes you made. Next month you drop in the new files and run it again.

macOS, Apple silicon and Intel; Windows is in progress. Free is not a trial — no account, no card.

Last reviewed 2026-09-15 by the TableDI team. Something wrong on this page? Tell us — it is one inbox, read by the people who build TableDI.