🔄 JSON to CSV Converter

Convert JSON arrays and objects to CSV format — handles nested objects, arrays, and mixed schemas. 100% in-browser, no data leaves your device.

Free No Upload Client-side
JSON Input
✓ Valid JSON ✗ Invalid

JSON Syntax Error

Supports arrays of objects, single objects, and objects with array properties  · 

Tip: Press Ctrl+Enter to convert

Conversion Options

How it works

1

Paste JSON

Array of objects, single object, or object containing an array

2

Choose options

Delimiter, flatten depth, array handling

3

Copy or download

Get your CSV — UTF-8 with BOM for Excel compatibility

🔄

No output yet

Paste your JSON on the left and click Convert to CSV to get started.

CSV Output
✓ Converted
📊 rows 📋 columns 💾 ⚙️
Preview first 5 rows
#
… and more rows in the CSV

Supported Formats

✅ Array of objects Recommended

[{"name":"Alice","age":30},
 {"name":"Bob","age":25}]

✅ Nested objects (flattened)

[{"name":"Alice",
  "address":{"city":"NY"}}]
→ columns: name, address.city

✅ Object with array property

{"users":[{"id":1},{"id":2}]}
→ auto-extracts "users" array

✅ Single object (1-row CSV)

{"name":"Alice","age":30}
→ 1 header row + 1 data row

From nested JSON to a flat table of columns

CSV is rectangular: one header row and a fixed set of columns. JSON is not, so the conversion has to flatten a tree into that grid.

The tool parses your input and finds the array of records. An array of objects is used directly, a single object becomes one row, and an object containing an array property has that array extracted.

Each record is then flattened. A nested object contributes one column per leaf value, with the path joined by your chosen separator, so a city inside an address becomes the column address.city. With flattening switched off, the whole nested object is written into one cell as a JSON string instead. Arrays inside a record are handled by the array option: joined into one cell with semicolons, written as JSON, or reduced to the first element.

The column set is the union of all keys across all records, so a field missing from one record leaves that cell empty. Finally each value is escaped: any cell containing the delimiter, a quote or a line break is wrapped in double quotes, and internal quotes are doubled.

Worked example: two records with nesting and an array

Take this input: an array of two objects. The first is name Alice, an address object containing city NY and postcode 10001, and a tags array of vip and eu. The second is name Bob, an address object containing city LA, and a tags array with one entry, trial.

With flattening on and the dot separator, the columns become name, address.city, address.postcode and tags: four columns drawn from the union of both records' keys. With the array option set to join with semicolons, Alice's tags become vip;eu and Bob's become trial.

The output is three lines: a header reading name,address.city,address.postcode,tags, then Alice,NY,10001,vip;eu, then Bob,LA,,trial. Bob's postcode cell is empty because that key is absent from his record, not because the value is zero.

The stats would report 2 rows and 4 columns. Switch the array option to stringify and Alice's cell becomes the JSON text for the array, which contains commas, so it is automatically wrapped in quotes to keep the row intact. Switch flattening off and address becomes one column holding the whole object as JSON.

Opening the result cleanly and avoiding data loss

Check the row and column counts against what you expected before you export. If the row count is one when you expected many, the parser probably found a single object rather than an array, or the array you wanted is nested deeper than the property it looked at.

Choose the delimiter to match your spreadsheet's locale. Software configured for a comma decimal separator, common across much of Europe, expects semicolon separated files and will otherwise drop everything into one column. Tab works well for pasting into a sheet directly, and pipe is useful when the data itself contains commas and semicolons.

Two classes of data survive the round trip badly. Long numeric strings such as identifiers, phone numbers and postcodes are often reinterpreted as numbers by spreadsheets, stripping leading zeros or switching to scientific notation. Quoting every cell helps with importers that respect quoting, but many spreadsheets still convert on open, so import as text where it matters.

Flattening is also lossy in one direction: once address.city is a column, the original nesting is gone, and converting back gives a flat object. Keep the JSON if structure matters.

Frequently Asked Questions

An array of objects works best and is the recommended input. A single object converts to one header row and one data row. An object that contains an array in one of its properties also works, because the tool extracts that array and treats its items as the records. A bare array of numbers or strings has no keys to make columns from.
Each leaf value becomes its own column, named by joining the path with your chosen separator. A city inside an address becomes address.city by default, and you can switch the separator to underscore, slash or double underscore. Turning flattening off instead writes the whole nested object into a single cell as JSON text.
Because the columns are the union of every key across all records, and that particular record does not have that key. An empty cell means the field was absent or null, not that it was zero. This is normal for JSON from APIs where optional fields appear only on some records.
Comma is the default and works with spreadsheets set to an English locale. Choose semicolon if your spreadsheet uses a comma as the decimal separator, which is standard across much of Europe, otherwise the whole row lands in one column. Tab suits direct pasting, and pipe helps when the data already contains commas.
That happens in the spreadsheet, not the conversion. CSV has no types, so an application seeing 01234 usually treats it as the number 1234. Import the file rather than double-clicking it and set those columns to text, or check the values against the JSON preview before relying on them.