Someone asks you for "the data in a spreadsheet". You have a JSON file. It should be a thirty-second job.

Then you look at the JSON properly. Each record has an address object nested inside it, a skills array with a different number of items per person, and a few fields that only appear on some records. A spreadsheet has no idea what to do with any of that — it wants a flat grid of rows and columns, and what you have is a tree.

Every JSON-to-CSV converter has to resolve that mismatch, and the choices it makes are what decide whether your output is genuinely useful or quietly wrong. This guide walks through exactly what happens to nested objects, arrays, and edge-case values during conversion — so you can look at a CSV and know it is right.

Why JSON and CSV Don't Line Up

The whole problem comes down to one sentence: JSON is a tree, CSV is a grid.

JSON can nest to any depth. An object can hold another object, which can hold an array of objects, forever. CSV has exactly two dimensions — rows and columns — and no way to express "this cell contains three more records". If keeping that nesting intact matters more than opening the file in a spreadsheet, converting to XML is the better target, since XML is a tree too. And if the destination really is a spreadsheet someone will work in, exporting to Excel keeps cell types that CSV throws away.

So converting JSON to CSV is not really a conversion. It is a flattening: the tree gets squashed into a grid, and the converter must decide how. There are only two moves available, and every tool uses some combination of them:

  • Nested objects become extra columns — the path to the value turns into the column name
  • Arrays become extra rows — one row per item, with the parent record's values repeated

Once you know which move a tool makes for each part of your data, its output stops being surprising.

Check your JSON is valid first A converter can only flatten JSON it can parse. If conversion fails immediately, the file itself is usually the problem — run it through the JSON Formatter to find the syntax error, or read our guide to formatting, minifying, and validating JSON.

How Nested Objects Become Columns

When a value is an object, its inner keys are pulled up and joined to the parent key to form new column names. This input:

{ "name": "John", "address": { "city": "Delhi", "zip": "110001" } }

produces three columns — address_city, address_zip, and name. The address object itself disappears; only its leaves survive as columns.

This works to any depth. An object three levels down simply produces a longer column name, joining each key along the path.

Underscore, not dot Many converters join nested keys with a dot (address.city). CodBolt uses an underscore (address_city). The underscore is usually the safer choice downstream: dots have meaning inside spreadsheet formulas and most SQL dialects, so dotted column names often need quoting before you can query them.

How Arrays Become Rows

Arrays are where conversions go wrong, because an array has no fixed size. A converter cannot know in advance whether a record has one skill or forty, so it cannot reserve columns for them.

The solution is row expansion, sometimes called denormalisation: the record is repeated once per array item. Take this single record:

{ "name": "John", "skills": ["JavaScript", "Python"] }

It becomes two rows, with name repeated on both:

name,skills John,JavaScript John,Python

The same applies to arrays of objects, with one extra detail: each child object's keys are merged into the row and prefixed with the array's field name. This record:

{ "name": "Beta", "orders": [ { "id": 1, "item": "pen" }, { "id": 2, "item": "book" } ] }

becomes two rows, with the parent's name repeated and the child's keys appearing as orders_id and orders_item:

name,orders_id,orders_item Beta,1,pen Beta,2,book

Two arrays in one record multiply

This is the part that catches people out, and most guides skip it. Row expansion runs for every array field independently — so a record with two arrays produces a row for every combination:

{ "name": "John", "skills": ["JS", "Python"], "tags": ["remote", "senior"] }

Two skills multiplied by two tags gives four rows, not two:

name,skills,tags John,JS,remote John,JS,senior John,Python,remote John,Python,senior

With three arrays of five items each, one record becomes 125 rows. That is correct output — every row is a real combination — but if you only care about one of those arrays, drop the others from your JSON before converting and the result stays compact.

Row counts are not a bug More CSV rows than JSON records is expected behaviour, not data corruption. Identical duplicate rows produced during expansion are removed automatically, but genuinely different combinations are all kept — because each one is real data.

What Happens to Awkward Values

CSV has no type system. Every cell is text, so each JSON type has to be represented somehow.

  • null becomes an empty cell. So does a missing key — which means you cannot tell "this field was null" apart from "this field wasn't there" by looking at the CSV.
  • Booleans become the text true and false. Most spreadsheets will read these back as booleans on import.
  • Missing keys still get a column. Column headers are collected across every record, so if only one record has an address, every other row gets an empty address_city cell. Your grid stays rectangular.
  • Values containing commas, quotes, or line breaks are escaped properly — wrapped in quotes so the CSV structure survives.

The Excel problem, and the apostrophe fix

Open a CSV in Excel and it will helpfully "interpret" your data: long numbers turn into scientific notation, leading zeros vanish, and phone numbers get mangled. This is Excel's behaviour on import, not a flaw in the CSV.

The standard defence is a leading apostrophe, which tells Excel to keep the value as text. CodBolt applies it automatically to values that look like phone numbers — anything made only of digits, dashes, plus signs, brackets, and spaces:

+1-555-0101 → '+1-555-0101

Two things to know about this. First, the same rule catches dash-separated dates such as 2024-01-15, which is usually what you want, since Excel would otherwise reformat them to your local date style. Second, the apostrophe is an Excel convention — if you are feeding the CSV into another program or a database importer rather than a spreadsheet, that character may need stripping first.

Your Column Order Will Change

One genuinely surprising behaviour: columns come out in alphabetical order, not the order the keys appeared in your JSON.

Because headers are gathered from every record before the grid is built — records can have different keys, after all — they end up sorted rather than in source order. Feed in a record with keys in this order:

{ "name": "John Doe", "email": "john@example.com", "age": 28, "country": "USA", "active": true }

and the CSV header comes back reordered:

active,age,country,email,name true,28,USA,john@example.com,John Doe

Nothing is lost and no values move — each value stays under its own header. But if a downstream import expects columns in a fixed position, reorder them after conversion rather than assuming your original order survived.

How to Convert JSON to CSV, Step by Step

  1. Open the JSON to CSV converter.
  2. Paste your JSON into the left editor, or click Upload to load a .json file up to 100 MB. An array of objects is the normal input, but a single object works too — it simply becomes one row.
  3. Click Convert. The CSV appears in the right editor.
  4. Check the row count against your record count. If it is higher, an array was expanded — scroll back to the arrays section above to confirm that is what you wanted.
  5. Use Copy for the clipboard, or Download to save the result as a data.csv file.

Click Sample first if you want to see the behaviour on known data — it loads three records and shows exactly how the columns come out.

Conversion runs entirely in your browser. The file is never uploaded anywhere, which matters when the export you are converting contains customer records.

Converting an export that looks wrong? If only some records come out badly, the problem is usually in the source JSON rather than the conversion. Diffing it against a known-good export is faster than hunting through the CSV — our guide on comparing two JSON files covers how. And if you need to go the other way afterwards, CSV to JSON handles the return trip.
Try it now — CodBolt JSON to CSV

Flattens nested objects, expands arrays, files up to 100 MB. Free and 100% private.

Open Tool