Converters

How to Convert JSON to CSV (Commas, Nesting and Delimiters Explained)

How to convert JSON to CSV: which JSON shapes convert cleanly, how commas and quotes are escaped per RFC 4180, what happens to nested objects, and choosing a delimiter, with a worked example.

6 min readUpdated Jul 12, 2026

JSON and CSV are two of the most common ways to move structured data around, and sooner or later you will have data in one when you need it in the other. JSON - JavaScript Object Notation - is the language of APIs, configuration files and web apps, where each record is an object with named fields. CSV - comma-separated values - is the language of spreadsheets, where every row is a record and every column a field. Turning a JSON array into CSV means flattening it into a plain grid that Excel, Google Sheets or a database importer can read. This guide explains which shapes of JSON convert cleanly, how special characters are escaped, how to choose a delimiter, and walks through a worked example you can reproduce in the JSON to CSV converter.

JSON and CSV are shaped differently

The core challenge is that the two formats do not describe data the same way. JSON is hierarchical: an object can nest other objects and arrays to any depth, and every record carries its own field names. CSV is flat and rectangular - just rows and columns, with a single header line naming the columns once at the top. To go from JSON to CSV you have to decide which JSON values become rows and which become columns, then squeeze any nesting into single cells. That is why not every JSON document converts neatly, and why the converter expects a specific overall shape.

The JSON shapes that convert to CSV

For a clean conversion the top level of your JSON must be an array, because each item in that array becomes one row of the spreadsheet. Within that, two shapes are supported:

  • An array of objects - the most common case. Every object is a row, and the object keys become the column headers. The converter scans all the objects and collects the union of their keys in first-seen order, so even if some records carry extra fields, every column still appears.
  • An array of arrays - where each inner array is already a row of values in order. This maps straight onto CSV rows without any key names, which is useful when your data is positional rather than labelled.

A bare object or a single value at the top level will not convert, because there is nothing to turn into multiple rows. If your JSON is wrapped - say the array you want sits inside a { "data": [ ... ] } envelope - pull out the inner array first. You can tidy and inspect the structure with the JSON Formatter beforehand so you can see exactly which array you need.

A worked example

Take this small array of objects, where one record is missing a field and one value contains a comma:

  • { "name": "Ada Lovelace", "role": "Engineer", "city": "London" }
  • { "name": "Grace Hopper", "role": "Rear Admiral", "city": "New York, NY" }
  • { "name": "Alan Turing", "role": "Mathematician" }

The converter first collects the union of keys in the order it meets them - name, role, city - and writes them as the header row. Each object then becomes a data row, looking up each column by key. The result is:

  • name,role,city
  • Ada Lovelace,Engineer,London
  • Grace Hopper,Rear Admiral,"New York, NY"
  • Alan Turing,Mathematician,

Three things are worth noticing. Grace Hopper's city is wrapped in double quotes because it contains a comma, which would otherwise be mistaken for a column break. Alan Turing has no city field, so his row simply ends with an empty cell rather than shifting the columns out of line. And because every column was discovered up front, the grid stays perfectly rectangular even though the source objects were not identical. Paste the three objects into the JSON to CSV converter and you get exactly these four lines back.

How commas, quotes and line breaks are escaped

CSV looks trivial until a value contains the very character used to separate columns. The widely followed RFC 4180 convention handles this, and the converter applies it automatically. A field is wrapped in double quotes whenever it contains the delimiter, a double quote, or a line break. Any double quotes inside such a field are then doubled - so a value like 5" (five inches) is written as "5""". This is exactly what Excel and Google Sheets expect, so a file produced this way opens with its columns intact even when the data is messy. Rows are separated with a carriage-return-and-line-feed pair, the line ending CSV readers handle most reliably across Windows, macOS and Linux.

What happens to nested objects and arrays

CSV has no concept of nesting - a cell holds one flat value - so an object or array sitting inside a field cannot be spread across columns. Rather than dropping it, the converter writes the nested value back as compact JSON text inside the single cell. A field whose value is { "lat": 51.5, "lng": -0.1 } shows up in the spreadsheet cell as the literal text {"lat":51.5,"lng":-0.1}, quoted in the file so its own commas do not break the row. This keeps the information intact, but if you need those inner values as their own columns you should flatten the JSON before converting - lifting, say, address.city up to a top-level city field.

Choosing the right delimiter

Comma is the default and the safest choice for anything you will import programmatically, but it is not always the best fit. The converter also offers semicolon, tab and pipe:

  • Semicolon is the expected separator in many European locales, where the comma is used as the decimal mark. If your spreadsheet splits a number like 1,5 into two columns, switch to semicolon.
  • Tab produces TSV (tab-separated values), which pastes cleanly straight into a spreadsheet and sidesteps comma clashes entirely.
  • Pipe ( | ) is common in data pipelines and log formats where commas appear frequently inside the values themselves.

Whichever you pick, the escaping rules follow it: with a semicolon delimiter, for instance, it is semicolons - not commas - inside a value that trigger quoting. Match the delimiter to whatever will read the file, and the rest takes care of itself.

Headers and missing fields

By default the first line of the output is a header row naming every column, which is what most spreadsheet and import tools expect. You can turn the header off if the receiving system wants raw data only - handy when appending to a file that already has its headers. Either way, records missing a field get an empty cell in that column rather than a shifted row, so the columns always stay aligned even when the source objects are not identical.

Converting cleanly - and going back

The reliable workflow is: make sure your data is a top-level array of objects, flatten any nesting you need as real columns, pick the delimiter your target expects, and paste it into the JSON to CSV converter. Everything runs in your browser, so even sensitive data never leaves your device, and you can copy the result or download it as a .csv ready for Excel or Sheets. To travel the opposite way - pulling a spreadsheet export back into structured data for an API or script - the CSV to JSON converter reverses the process, using the header row as the object keys.

Frequently asked questions

What JSON do I need to convert to CSV?
The top level must be an array. Each item in the array becomes one row: an array of objects turns the object keys into column headers, while an array of arrays maps each inner array straight onto a row. A single object or plain value at the top level will not convert, so wrap or extract the array you want first.
Why are some values in my CSV wrapped in double quotes?
A field is quoted whenever it contains the delimiter (a comma by default), a double quote, or a line break, following the RFC 4180 CSV standard. This stops those characters being read as column or row boundaries, and any double quotes inside the value are doubled. It is exactly what Excel and Google Sheets expect, so the file opens with its columns intact.
What happens to nested objects in my JSON?
CSV cells hold a single flat value, so a nested object or array is written back into the cell as compact JSON text rather than spread across columns. If you need those inner values as their own columns, flatten the JSON first - for example lifting address.city up to a top-level city field - before converting.