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 |
|---|
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.
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.
How to use
- 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 conversions people actually run
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
Tips & best practices
- 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.
- If your JSON is minified or you are not sure it is valid, run it through the JSON formatter first — 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.
Gotchas — where this conversion loses data
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.
Technical details
- 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.
Frequently asked questions
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.