Developer

How to Convert JSON to CSV When Your Data Is Nested

Every key becomes a column and every object becomes a row. The decisions start the moment something in your JSON is not flat.

A JSON array of objects becomes a CSV by taking every key that appears anywhere in the array as a column and writing one row per object, so [{"id":1,"name":"Ada"}] comes out as a header line id,name and a row 1,Ada. Paste the array into the converter on this page and that is the file you get back, quoted the way RFC 4180 asks. The awkward part is everything JSON can express that a rectangle cannot: nested objects, arrays, types, and the difference between null and an empty string.

What the converted file actually looks like

Take an array with a nested object and an array in it, like most API responses:

[
  { "id": 1, "name": "Ada Lovelace", "address": { "city": "London" }, "tags": ["maths"] },
  { "id": 2, "name": "Hopper, Grace", "address": { "city": "New York" }, "tags": [] }
]

The CSV is this:

id,name,address.city,tags
1,Ada Lovelace,London,"[""maths""]"
2,"Hopper, Grace",New York,[]

Three things happened there. The nested address object turned into a dotted column. The tags array stayed as JSON text in a single cell. And the name containing a comma got wrapped in quotes, because otherwise it would have split into two columns and shifted everything to the right of it.

The columns are the union of every key across every object, in the order each first appears. A row missing a key gets an empty cell rather than a short row, so ragged data stays lined up instead of sliding sideways halfway down the file.

Does your JSON have rows in it?

An array of objects is the case this works for. A single object converts too and gives you one row. An array of plain values becomes a one-column table.

Plenty of JSON has no rows in it at all, and forcing it into a spreadsheet gives you something valid and useless. A config file, a settings tree or a decoded token payload each convert into one wide row of dotted columns. The claims inside a JWT read far better as JSON than as forty columns you scroll sideways through.

If the text is one long minified line and you cannot tell what shape it is, run it through a JSON formatter first. It flags the two problems that parse cleanly and still hurt: duplicate keys, where the last one silently wins, and integers too large for JavaScript to hold exactly. The converter mentions neither. Reading minified JSON covers the rest of that.

What happens to nested objects and arrays

This is the part that cannot be done correctly, only decided. Three cases, three compromises.

Nested objects: dotted columns

{"address":{"city":"London"}} becomes a column called address.city, and the dots keep going as deep as your data does. An object with nothing in it has no keys to borrow, so {"address":{}} comes out as a column called address holding the text {}. Switch flattening off and every object lands in one cell that way — easier to read when a person is going to open the file, useless when a program has to parse it.

Arrays of values: one cell, as JSON

["maths","notes"] stays as that text in a single cell. The alternative is a column per position, and then one row with forty tags widens the file for every other row, most of them blank. If you want maths; notes in the cell instead, join the array in the JSON before you convert.

Arrays of objects: pick which way to be wrong

Orders with line items, posts with comments. One-to-many has no flat form that keeps everything. Leave the child array as JSON in its cell and the spreadsheet can do nothing with it. Repeat the parent fields once per child and the file reads well until someone sums a column, at which point every order total is counted as many times as it has items. If you need the second, split the JSON into a parent table and a child table sharing an id, and convert them separately.

Why some fields come out wrapped in quotes

Those quotes are not part of your data. They are the only way CSV has of saying that a comma or a line break inside a field is content rather than a separator, and the next parser strips them on the way in. Deleting them by hand is how a working file stops working.

A field gets wrapped when it contains the delimiter, a double quote or a line break. A quote inside a wrapped field is doubled rather than backslash-escaped, so Alan "Turing" is written "Alan ""Turing"""; backslashes are a different convention and most importers will not understand them. Fields with leading or trailing spaces are wrapped here as well, which the rules do not require but which saves you from the parsers that quietly trim unquoted whitespace.

A field holding a line break makes one CSV row span two lines of the file. That is legal, and it breaks anything that reads the file a line at a time — which is most quick scripts.

The rules come from RFC 4180, published in 2005 and marked informational: it recorded what people were already doing instead of telling anyone what to do, which is why importers still disagree with each other. Rows end with CRLF, as the RFC asks and as Excel prefers. Unix tools read that without complaint, except that some of them leave the carriage return stuck to the last field of every row. If an importer you do not control keeps refusing the file, quoting every field is verbose and never wrong.

Why every column lands in cell A1

Because your spreadsheet expects a different delimiter. Excel follows the system list separator, which is a semicolon across much of Europe and Latin America, where the comma is already the decimal mark. Open a comma-delimited file there and the whole row lands in cell A1. Switching the delimiter to semicolon fixes it. Tab does the same job with far less quoting, since tabs almost never appear inside real data.

Why the accents arrive as garbage

If José opens as José, the file is fine and the reader is wrong. Excel on Windows still opens a plain .csv using the system's legacy code page rather than UTF-8. A byte order mark — three bytes at the start of the file — tells it otherwise, which is why the converter here writes one into the download by default.

Leave it on for Excel. Turn it off when the file is going into a script, a database loader or a Unix pipeline, where those three bytes end up glued to the front of your first column name and produce a baffling error. The BOM goes into the downloaded file only, never into the text you copy.

What a spreadsheet changes the moment you open it

The CSV can be perfect and the spreadsheet will still edit it on the way in, because double-clicking a file lets it guess at every column.

The fix is to stop double-clicking. In Excel, use Data, then From Text/CSV, and set the awkward columns to Text during the import. In Google Sheets, use File, then Import, and switch off the option that converts text to numbers, dates and formulas. None of it is the file's fault; the damage happens on the other side.

Why a cell that starts with = is a security problem

A cell whose text begins with =, +, @, a tab, or a minus sign that is not the start of a number is evaluated as a formula rather than shown. When the data came from users, that formula runs on the machine of whoever opens the export. It has a name — CSV injection — and it is a real attack route, not a curiosity.

The converter counts those fields and tells you how many there are. It does not neutralise them, deliberately: the usual fix is prefixing an apostrophe, which corrupts the value for every non-spreadsheet reader of the file. Whether that trade is worth making depends on where the file is going.

What the conversion loses

Types. CSV has none. 42, "42" and true all become plain text, and whatever reads the file next has to guess them back. That guessing is where converting a CSV back to JSON goes wrong, which is why a JSON to CSV to JSON round trip does not return what you started with.

Null. null and an empty string both come out as an empty cell; CSV cannot tell them apart.

Very large integers. Past 9007199254740991, JavaScript can no longer hold every whole number exactly, so an ID that long may have been rounded when the JSON was parsed — before the CSV existed, and with nothing in the CSV to show for it. IDs that big have to be strings in the JSON.

Size. There is no streaming. The text, the parsed value and the finished CSV all sit in memory at once, so a few megabytes is comfortable and a hundred is not. Past that point — or past the second time you do it — write the script instead.

The JSON to CSV converter here does all of the above in the tab you have open — parsing, flattening, quoting and the download — so customer data never leaves your machine. It also counts the columns that were missing from some rows and the fields a spreadsheet will treat as formulas, which are the two things you would otherwise discover after sending the file.

If you are moving data the other way as well, converting CSV to JSON is the harder half of the round trip: going down loses structure, and coming back up means guessing types, which is how ZIP codes lose their leading zeros.

Frequently asked questions

How do I convert JSON to CSV?

Paste a JSON array of objects into a converter and it writes one row per object, using every key that appears as a column. Check the delimiter matches what your spreadsheet expects, then copy the result or download the file. Browser-based converters do this without sending the data anywhere.

How do I convert nested JSON to CSV?

Nested objects are flattened into dotted columns, so address.city becomes its own column. Arrays are kept as JSON text in a single cell, because expanding them would add a column for every element. An array of objects, like line items inside an order, has no flat equivalent at all — split it into two tables with a shared id and convert them separately.

Why does Excel show my whole CSV in one column?

Excel uses the system list separator rather than always assuming a comma, and in most of Europe and Latin America that separator is a semicolon. Regenerate the file with semicolons, or use Data, then From Text/CSV, where you can choose the delimiter during the import.

Why did my leading zeros disappear after I opened the CSV?

They are still in the file. Excel and Google Sheets guess a type for every column when you open a CSV directly, and a value like 01234 is read as the number 1234. Import the file instead of double-clicking it, and mark those columns as Text.

Can I convert JSON straight to an Excel file?

Not here — the output is CSV or TSV, not .xlsx. That is usually enough, since Excel opens both, but it means no formatting, no multiple sheets and no column types stored in the file. Keep the UTF-8 byte order mark switched on so accented characters survive the trip into Excel on Windows.

Is it safe to convert JSON to CSV online?

Only if the page does the work in your browser. Many converters post your text to a server, where it lands in logs and backups you never see. Check before pasting anything covered by a privacy agreement, and prefer a tool that states it never transmits the input.

Last updated September 19, 2026