JSON to CSV converter
This page takes JSON and writes a flat CSV table that spreadsheets and databases can open. Objects become columns, nested objects become dotted column names such as address.city, and anything that cannot be flattened is written as JSON text inside a cell. It is a shape change, not a lossless round trip.
Nested objects are flattened into columns like address.city.
Processed on your device. Files aren’t sent anywhere.
How the converter reads your JSON
The file must parse as JSON; invalid syntax is reported as a decode error and nothing is written. An array of objects becomes one row per element. A single object becomes one row. If the top-level object contains arrays, the first array found is used as the row list - so an object like {"users": [...]} converts the users rather than the wrapper.
A plain scalar (a number or string at the top level) becomes a single row under a column named value. That keeps the data present rather than silently dropping it.
- Array of objects: one row per element, one header row
- Single object: one row
- Object containing an array: that array is treated as the rows
- Scalar value: one row in a column called value
Nested objects become dotted columns
Flattening walks nested objects and joins the keys with a dot: address.city, contact.phone, meta.author.name. Each row contributes whatever it has; rows missing a key produce an empty cell for that column.
Arrays are not spread across columns - they are written as JSON text in a single cell, so tags: ["a","b"] appears as the literal string ["a","b"].
Columns are collected from every row
The header is the union of keys seen across all rows, in the order they first appear. Ragged data therefore produces a wide header with blank cells rather than an error - useful for spreadsheets, but worth checking before importing.
Separator choice and quoting
The Separator control offers Comma, Semicolon and Tab. Regional spreadsheet setups often expect semicolons, and tab-separated output pastes cleanly into editors.
A cell is quoted only when it needs to be: if it contains the separator, a quote, or a line break. Inner quotes are doubled in the standard way, so text containing quotes survives the round trip.
- Comma: default, standard CSV
- Semicolon: common in European spreadsheet locales
- Tab: TSV-style output that pastes well
- Quoting is applied per cell, not to the whole row
A BOM is added for spreadsheet apps
The output starts with a byte-order mark so spreadsheet software reads it as UTF-8. Accented characters and non-Latin text are preserved in the file rather than mangled, but the BOM can look odd in plain text editors.
What changes and what is lost
CSV is a flat text table: no types, no nesting, no structure. Numbers and strings both become text in cells, and null becomes an empty cell. Booleans become their text names. There is no way to reconstruct the original JSON shape from the CSV alone.
Keys that differ only in case or spacing can produce confusingly similar column names, since the converter does not normalise or merge them.
- Lost: nesting, types, null as a distinct value, key ordering guarantees
- Kept: row count, cell text, column names derived from keys
- Not attempted: merging records, deduplicating keys, preserving JSON formatting
Empty and missing values
A missing key yields an empty cell. An explicit null also yields an empty cell, so the two are indistinguishable in the CSV. If that distinction matters, keep the JSON.
Limits and practical use
Each input file may be up to 50 MiB and you can convert up to 10 files at a time. Everything runs in this browser tab, so records containing personal data never leave the device.
Typical uses: exporting an API response into a spreadsheet, preparing a contact list for import, or turning a nested config dump into something a colleague can read.
- Up to 10 files, 50 MiB each
- Output row count is reported after conversion
- Invalid JSON is rejected with a decode error rather than partially converted
Round-tripping is not symmetric
Converting the CSV back to JSON gives an array of objects keyed by the dotted column names, with plain numbers typed as JavaScript numbers. Original nesting is not restored, and very large integer identifiers can lose precision when typed.