JSON to CSV Converter_
Paste a JSON array and get a CSV file a spreadsheet will open. This converter takes the shape you actually have — an array of records, a single object, an API response like {"data": [...]}, or JSON Lines — flattens the nested parts the way you choose, and shows you the exact column list before you download anything.
It runs entirely in this tab. That matters more here than on most pages: the JSON people convert to CSV is usually an export of real records — customers, orders, invoices — and several of the best-known converters process on a server, one of which documents that saved data becomes public unless you have an account.
| Column | In how many records |
|---|
- Input
- JSON: an array of objects, a single object, or a response with the records buried a level or two down.
- Output
- CSV with a header row, RFC 4180 quoting, and your choice of delimiter and line ending — plus an optional BOM so Excel opens it in the right encoding.
- Processing
- Flattened in this tab. Every column the conversion produced is listed before you download, because a column you did not expect is the usual way this goes wrong.
- Limits
- CSV is a rectangle and JSON is a tree, so records that do not share a shape cannot all fit. The union of keys becomes the header and the gaps become empty cells, which is a decision rather than a failure.
- Nesting
- A nested object can become dotted columns, a JSON string inside one cell, or nothing at all. There is no correct answer — only the one that suits whatever opens the file next, which is why it is a setting and not a guess.
How to convert JSON to CSV, and what it costs
The conversion in one sentence
Every record becomes a row, every field becomes a column, and the header row names the columns. That is the whole of it when your JSON is already flat. The work — and every decision worth making — is in what happens when it is not.
Why nesting has no correct answer
CSV is a rectangle. JSON is a tree. There is no arrangement of rows and columns that holds a tree without losing something, so every converter picks a lossy strategy — and most pick it for you without saying so. Dot notation promotes address.city to its own column, which is readable and sortable but cannot represent an array of different lengths. Writing the nested value into a cell as JSON keeps everything, at the cost of a column your spreadsheet cannot do anything with. Exploding an array into rows is right for line items and wrong for anything where a record must stay one row. This page makes you pick, shows the resulting columns, and names what each choice costs.
Converting JSON to CSV in Python
For a flat array, the standard library is enough: csv.DictWriter(f, fieldnames), writeheader(), then writerows(records) — and it handles RFC 4180 quoting for you. For nested data, pandas.json_normalize(records) does the same dot-notation flattening this page does by default, and .to_csv("out.csv", index=False) writes it. Add encoding="utf-8-sig" to get the BOM, or Excel will mangle accented characters exactly as described below. For an array inside a wrapper, pass record_path to json_normalize.
Converting JSON to CSV in Excel
Excel can do it without a converter: Data → Get Data → From File → From JSON opens Power Query, where To Table and then the expand button on each column does the flattening one level at a time. It is genuinely capable and genuinely slow — a dozen clicks per nested level, repeated every time the file changes. Use it when the conversion is part of a refreshable query; use a converter when you want the file once.
Paste the JSON, choose the flattening, check the columns
- 01Paste or upload your JSON. The tool names the shape it found — an array, a single object, an array inside a wrapper, or JSON Lines — so you know it read what you meant before you look at the output.
- 02Choose how nested data is handled. This is the decision that matters and the table above shows exactly what each option produces; the JSON to CSV conversion is only as good as this choice.
- 03Read the column list. It names every column you will get and how many records actually contain it — a column present in 3 of 5 records is the classic sign that the records are not the same shape.
- 04Set the delimiter and line endings for wherever this is going. Comma and CRLF suit Excel; semicolon suits most of continental Europe; tab pastes straight into a sheet without an import dialog.
- 05Copy the result or download the .csv. Leave the BOM on if a human will open it in Excel, and leave the injection guard on unless you know every value in the file.
Four payloads and the shape each one lands in
An API response into a spreadsheet
The endpoint returns a wrapper object, not a bare array — the shape most converters refuse.
{"status":"ok","data":[{"id":1,"name":"Ada"},{"id":2,"name":"Grace"}]}id,name 1,Ada 2,Grace
Catching records that are not all the same
Half the exported users have a phone number. The column report says so before you send the file on.
[{"id":1,"phone":"555"},{"id":2}]phone — 1 of 2 records
Order line items, one row each
An order with three items should be three rows carrying the same order id — that is Explode rows.
[{"order":"A1","items":[{"sku":"X"},{"sku":"Y"}]}]order,items.sku A1,X A1,Y
A file for a colleague in Germany
Their Excel expects semicolons and will put a comma-separated row into one cell.
Delimiter: Semicolon ;
id;name 1;Ada
What happens to nested data, side by side
| Field in the JSON | Dot notation (default) | JSON in cell | Explode rows |
|---|---|---|---|
"id": 7 | id → 7 | id → 7 | id → 7 |
"address": {"city": "London"} | address.city → London | address → {"city":"London"} | address.city → London |
"tags": ["a", "b"] | tags → a; b | tags → ["a","b"] | tags → a; b |
"items": [{"sku":"X1"}, {"sku":"X2"}] | items.0.sku, items.1.sku — two columns | items → the whole array as JSON | items.sku — two rows, the other fields repeated |
| Lossless? | No — the joined array cannot be taken apart again | Yes | No — which row came from which record is gone |
The default is dot notation because it is the only mode you can sort and filter on in a spreadsheet, which is usually why you wanted CSV. Switch to JSON in cell when the CSV is a staging step rather than a destination.
RFC 4180 quoting, rule by rule
| Rule | Value | Written as |
|---|---|---|
| Plain text is never quoted | Ada | Ada |
| A value containing the delimiter is quoted | London, UK | "London, UK" |
| A double quote is doubled, and the field quoted | say "hi" | "say ""hi""" |
| A value containing a line break is quoted | two⏎lines | "two⏎lines" |
| Leading or trailing spaces are quoted | 42 | " 42" |
| Empty and null are both the empty field | null | (nothing between the delimiters) |
Doubling is the only escape RFC 4180 defines — there is no backslash escape in CSV, and a writer that emits one produces a file Excel reads wrongly. Leading-space quoting is our addition: the standard does not require it, but Excel silently trims an unquoted field.
Habits that keep a converted sheet trustworthy
- Look at the column list before the CSV. It is faster than reading the output, and it is where sparse columns and surprise nesting show up.
- Keep the BOM on for anything a person will open in Excel, and turn it off for anything a program will read — some parsers treat the BOM as part of the first column name.
- Tab-delimited output pastes directly into a spreadsheet cell without triggering an import dialog. It is the fastest route from here to a sheet.
- You cannot choose a flattening for structure you cannot see, so if the payload arrived minified, open it in the JSON formatter before you decide anything — its errors name the line and column, which no converter can do once parsing has failed.
- Long numeric ids should be strings in the JSON before they get here. Once a 19-digit id is a JSON number, the precision is gone before any converter sees it.
- Converting two exports to compare them? Convert both with identical settings and put them through the diff checker — sorted, identically flattened CSV diffs cleanly where JSON does not.
- Quote every field when the consumer is a naive parser you did not write. It is larger and it removes a whole class of argument about edge cases.
- Explode rows changes what a row means: it is no longer one record. Check that whatever consumes the file expects that before you use it.
Where a flat file quietly drops something
Nested data has no faithful flat form
Something is always lost. Dot notation cannot recover an array of primitives from the joined cell, because "a; b" is what both ["a","b"] and ["a; b"] produce. Explode rows loses which output rows came from the same record. JSON in cell is the only lossless mode, and it costs you the ability to use the column as a column. Pick deliberately; the tool will not pretend the choice is free.
Mixed-shape records make sparse columns that look like missing data
When some records have a field and others do not, the CSV shows empty cells — and CSV cannot tell "the field was absent" from "the field was an empty string" or from null. All three are nothing between two delimiters. The column report names how many records actually contained each field, which is the only place that distinction still exists.
Excel rewrites your values as it opens them
A value like 3-4 or 1/2 becomes a date. A product code like 00123 loses its leading zeros. A 19-digit identifier is rounded to 15 significant digits and the last four become zeros — silently, on open, with no warning. The file on disk is correct; what you see is not. Import via Data → From Text/CSV and set those columns to Text, or prefix the values before export.
A value can become a formula
A cell starting with =, +, -, @, tab or a carriage return is executed by Excel and Google Sheets when the file is opened — this is CSV injection, and it is a real way to run code on a colleague's machine using data you merely passed along. The guard here prefixes affected string values with an apostrophe, which spreadsheets treat as literal text. It applies to strings only: a JSON number of -5 is written as -5, because prefixing it would turn a number into text. Note that Excel may strip the apostrophe if the file is saved and reopened, so the guard protects the first open rather than the file forever.
The delimiter is a local convention, not a standard
In much of continental Europe the decimal separator is a comma, so Excel there uses a semicolon to separate fields — which is why the option exists. Send a comma-separated file to that colleague and every row arrives in a single cell. If you do not know which they use, tab-delimited works everywhere.
Server-side converters see your customer records
The JSON people convert to CSV is typically an export: users, orders, invoices, support tickets. Several of the best-ranked converters process on a server, offer to load your data from a URL, and give you a shareable result link — and at least one documents that data saved without an account becomes public. Read what a converter does with your input before pasting anything real into it, here included: this page runs in your browser, which you can verify by disconnecting and using it anyway.
Flattening rules, quoting rules, and the limits
- File handling
- Uploads are read inside the page with the browser File API and are never transmitted; Download writes out what is already in the tab.
- Quoting
- RFC 4180 — embedded quotes doubled; fields containing the delimiter, a quote, CR or LF always quoted; leading and trailing spaces also quoted
- Accepted input
- Array of objects · a single object · an object containing an array · JSON Lines (one object per line)
- Delimiters
- Comma, semicolon, tab, pipe
- Line endings
- CRLF (RFC 4180 default) or LF, with exactly one terminating newline
- Encoding
- UTF-8, with an optional leading BOM (U+FEFF) so Excel reads accented characters correctly
- Injection guard
- Leading apostrophe on string values beginning = + - @ tab or CR; never applied to numbers
- Limits
- Input refused above 12 MB, checked before parsing; the output pane is truncated above 2 MB while Copy and Download give everything
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Questions about flattening JSON into rows
How do I convert JSON to CSV?
Paste the JSON on the left and the CSV appears on the right. If your data has nested objects or arrays, pick a flattening mode first — that choice decides what the columns are, and the table above shows what each one produces.
My JSON is an object, not an array. Will it work?
Yes. A single object converts to one row. An object wrapping an array — the usual API response shape — is detected and the array inside it is used, with the property name shown so you can confirm it picked the right one.
What happens to nested objects and arrays?
Whatever you choose. Dot notation gives address.city its own column, JSON in cell writes the nested value as JSON into a single cell, and Explode rows turns each element of an array into its own row. Only JSON in cell is lossless.
Why are some of my columns empty?
Because those records did not have that field. The column report tells you how many of the records contained each column — a count below the total is the signal. CSV itself cannot distinguish an absent field from an empty one.
Why does Excel show my file as gibberish or ruin my IDs?
Two separate problems. Accented characters need the UTF-8 BOM, which is on by default here. Long numeric IDs and values that look like dates are rewritten by Excel on open regardless of the file; import through Data → From Text/CSV and set those columns to Text.
Should I use a comma or a semicolon?
A comma unless the file is going to a locale that uses a comma as the decimal separator, which is most of continental Europe — Excel there splits on semicolons. Tab is a safe third option that works in both.
What is the CSV injection option for?
A cell beginning with =, +, -, @, tab or a carriage return runs as a formula when a spreadsheet opens the file. The guard prefixes such string values with an apostrophe so they stay text. It is on by default because the destination of a CSV is a spreadsheet.
How do I convert JSON to CSV in Python?
For flat records, csv.DictWriter with writeheader() and writerows(). For nested data, pandas.json_normalize(records).to_csv("out.csv", index=False, encoding="utf-8-sig") — json_normalize does the same dot-notation flattening this page defaults to, and utf-8-sig writes the BOM.