Convert JSON to CSV: Flatten an Array of Objects

A JSON array of objects maps to a CSV table — one row per object, columns from the union of keys. The real work is quoting and handling nested values.

The Array-of-Objects Shape

CSV (per RFC 4180) is a flat table, so the JSON that converts cleanly is an array of objects: each object becomes a row, each key becomes a column. The JSON to CSV tool applies the rules below in one pass, in your browser.

[
  { "name": "Ada Lovelace",  "year": 1815, "city": "London" },
  { "name": "Alan Turing",   "year": 1912, "city": "London" },
  { "name": "Grace Hopper",  "year": 1906, "city": "New York" }
]
name,year,city
Ada Lovelace,1815,London
Alan Turing,1912,London
Grace Hopper,1906,New York

JSON nested objects, arrays, or values with no flat shape need extra handling — covered below.

Building the Header

Use the union of every object's keys as the header, not just the first object's. That way, records with extra or missing fields still line up — missing cells just become blank:

[
  { "id": 1, "name": "Ada",   "city": "London" },
  { "id": 2, "name": "Alan",  "city": "London",   "email": "alan@example.com" },
  { "id": 3, "name": "Grace", "country": "USA" }
]
id,name,city,email,country
1,Ada,London,,
2,Alan,London,alan@example.com,
3,Grace,,,USA

If you only used the first record's keys, email and country would be silently dropped.

Quoting Rules

Per RFC 4180, any value containing a comma, double quote, or newline must be wrapped in double quotes — and any embedded double quote inside the value is doubled:

In JSON In CSV
"hello" hello (no quoting needed)
"hello, world" "hello, world" (comma forces quoting)
"line 1\nline 2" "line 1\nline 2" (newline forces quoting)
"she said \"hi\"" "she said ""hi""" (embedded quote doubled)
" spaces " " spaces " (preserve leading/trailing whitespace)

Skip any of these and the columns will misalign on the receiving side.

Nested Values

Objects and arrays have no flat CSV form. Two strategies, both legitimate:

// JSON
[{ "name": "Ada", "address": { "city": "London", "zip": "SW1A 1AA" } }]
# Strategy A — nested JSON inside the cell (reversible)
name,address
Ada,"{""city"":""London"",""zip"":""SW1A 1AA""}"

# Strategy B — flatten to dotted columns (analytics-friendly)
name,address.city,address.zip
Ada,London,SW1A 1AA

Strategy A round-trips cleanly back to the original JSON. Strategy B is the right shape for spreadsheets and BI tools but is lossy — repeated arrays or sub-objects with varying keys don't flatten neatly.

Header Order and Stability

Sort the union of keys, or freeze the order to the first record's keys with new ones appended at the end. A stable header order makes diffs across exports useful and avoids reshuffling columns every run — which matters when a downstream pipeline keys off column position rather than name.

Date and Number Formatting

Spreadsheets reinterpret values aggressively, often silently. The recurring traps:

  • Long numeric IDs lose precision: a 16-digit account ID like 9007199254740993 becomes 9.00719925474099e+15 in Excel.
  • ISO dates get reformatted: 2026-06-20 becomes 6/20/2026 (or 20/6/2026, locale-dependent).
  • Leading zeros disappear: 007 becomes 7.
  • Scientific-notation-looking strings get coerced: 1E10 becomes 10000000000.

If a value must round-trip exactly, wrap it in quotes in the CSV and prefix it with a single quote (') when pasting into Excel — Excel then treats it as a literal text cell.

Excel and Google Sheets Compatibility

For broad compatibility, write CSV with:

  • CRLF line endings (\r\n) — RFC 4180's mandated separator.
  • UTF-8 with a BOM (EF BB BF at the start) — Excel needs this to detect Unicode; without it, accented characters and emoji render as mojibake.
  • Comma delimiters, is the spec; semicolons (;) are common in European locales but non-standard.
  • Double-quote escaping" doubled, not backslash-escaped.

Google Sheets accepts files without the BOM but follows the same comma + double-quote rules.

Going from CSV Back to JSON

The reverse direction is its own minefield. Parse rows with quote-aware splitting (do not split on commas naively — embedded commas inside quoted fields will misalign every row), use the first row as field names, and try to coerce numbers, booleans, and ISO dates per column. Round-tripping via the JSON to CSV tool keeps strings as strings unless a column is uniformly numeric.

Common Pitfalls

The issues that break most CSV exports, in rough order of frequency:

Pitfall Fix
Unescaped commas inside string values Quote any field containing ,, ", or \n
Newlines in cells without surrounding quotes Quote multi-line fields
Mixed encodings (UTF-8 vs Latin-1) producing mojibake Write UTF-8 with BOM
Large integers (IDs) silently truncated by spreadsheets Quote the value or import the column as text
Boolean values stored as "true" / "false" strings Pick one convention per pipeline; spreadsheets often want TRUE / FALSE
Header row missing or named inconsistently across exports Sort or freeze header order

See also

This guide handles one format boundary. The hub lists every JSON ↔ neighbor-format conversion with its standard and edge cases.

Sources

  • RFC 4180 — the canonical CSV specification (IETF)
  • RFC 8259 — the JSON Data Interchange Format
  • MDN — Array.prototype.map (the natural JS pattern for the array-of-objects → rows transform)

Last reviewed June 2026.