JRJI
All articles
Guides · 7 min

Turning JSON into CSV without losing your mind

A practical guide to flattening nested records for spreadsheets, with the edge cases nobody warns you about.

“Just export it to CSV” sounds like a five-minute task until you actually try it. JSON is a tree; CSV is a grid. Converting one into the other means deciding, case by case, how to squash a hierarchy into rows and columns — and every dataset hides at least one edge case that breaks the naive approach.

Here is the mental model, plus the traps.

Start from the right shape

CSV conversion works cleanly on exactly one JSON shape: an array of flat objects.

[
  { "id": 1, "name": "fixer", "hits": 830 },
  { "id": 2, "name": "diff",  "hits": 1420 }
]

Each object becomes a row; the union of all keys becomes the header. If your data is not in this shape yet, your first job is to get it there — usually by finding the array buried inside a wrapper (data.results, items, rows) and lifting it out.

Trap 1: ragged objects

Real-world records rarely share an identical key set. Record 1 has email, record 2 doesn’t; record 5 introduces phone. A converter that reads columns from the first object silently drops fields from later ones.

The correct behavior — and what JRJI’s converter does — is to take the union of keys across all records as the column set, leaving cells blank where a record lacks a key. Blank, not "undefined", not "null": spreadsheet formulas treat empty and the string "undefined" very differently.

Trap 2: nested values

{ "id": 1, "author": { "name": "kim", "role": "admin" }, "tags": ["a", "b"] }

A grid cell can’t hold an object. You have three options, in increasing order of effort:

  1. Stringify — the cell holds {"name":"kim","role":"admin"}. Lossless, ugly, fine for eyeballing.
  2. Flatten with path keys — columns become author.name, author.role. Best for one or two levels of nesting.
  3. Explode arrays into rows — one row per tag, duplicating the parent fields. Correct for one-to-many data, but it changes your row count and semantics; do it deliberately, not by default.

There is no universally right answer, which is why “simple” converters disagree with each other. Know which one your tool does before trusting the output.

Trap 3: CSV escaping

CSV’s quoting rules are where casual converters corrupt data. The rules that matter:

  • A value containing a comma, double quote, or newline must be wrapped in double quotes.
  • A double quote inside a quoted value is escaped by doubling it: He said ""hi"".

Get this wrong and a single free-text field with an embedded comma shifts every subsequent column in that row. If you have ever opened an export where someone’s address ended up in the “salary” column — this is why.

Trap 4: Excel’s helpful sabotage

Your CSV can be perfectly valid and still get mangled on open:

  • Leading zeros vanish: zip code 01234 becomes 1234.
  • Long digit strings (IDs, card numbers) get rounded into scientific notation past 15 digits.
  • Anything date-like (1/2, MARCH1 — famously, gene names) is converted to a date.

The defense is to import via Data → From Text/CSV and declare column types, rather than double-clicking the file. If the audience will double-click anyway, consider prefixing risky values to force text interpretation.

A sane default workflow

  1. Reduce your JSON to an array of objects (fix broken input with the Fixer first if needed).
  2. Convert with union-of-keys columns and strict escaping — the JSON to CSV tool handles both, entirely in your browser.
  3. Spot-check row count and one ragged record before shipping the file to whoever asked for “just a CSV”.

The conversion itself takes a click. Knowing what the click did to your nested fields is the part that keeps your data honest.