Skip to content

JSON ↔ CSV Converter

Options

CSV output

Type input to begin

Estimates for educational purposes — not financial, medical, or legal advice. See terms.

JSON and CSV are both common data-interchange formats with very different shapes. JSON handles nested structures, types, and arbitrary key sets per object. CSV is strictly tabular: rows and columns, every value a string, the same columns for every row. Going from one to the other is a flattening operation; going back is a typing-and-grouping operation. Most “JSON to CSV” or “CSV to JSON” frustration comes from underestimating the impedance mismatch.

This tool handles both directions in your browser, with RFC 4180-compliant CSV quoting and the conventions most tools expect.

How JSON → CSV works

The converter expects the top-level JSON to be an array of objects. Each array element becomes a CSV row. The header row is the union of all keys across all objects, in first-seen order. Missing keys fill empty cells. Nested objects and arrays are JSON-stringified into a single cell — CSV has no native nested data, so this preserves the structure as text round-trippable through JSON.parse.

Cells are quoted per RFC 4180: only when they contain the delimiter, a ", or a line break. Quotes inside a cell are doubled ("" → literal "). The result is the minimum-quoted form that any compliant CSV reader can parse unambiguously.

How CSV → JSON works

The parser handles RFC 4180 quoting (doubled quotes, embedded delimiters, embedded newlines) and three line-ending conventions (\n, \r\n, \r). With “first row is header” on, you get an array of objects keyed by the header. Without it, you get an array of arrays of strings.

Values are always returned as strings — CSV has no types, and guessing whether "42" is a number or a string is the kind of decision that should live in your application code, not in a generic converter. Post-process with Number(row.score) or a schema library.

Example: exporting a database query result

Your database query returned an array of records as JSON. You need a CSV to import into Google Sheets. Paste, switch to JSON → CSV, comma delimiter, include header. Copy. Paste into Sheets. Done.

If your records have nested fields (like a tags array on each row), those become JSON-encoded cells — Sheets will display them as text, which is fine for one-off use. For repeated workflows where you want each tag in its own column, flatten the JSON first.

Example: importing a CSV with European semicolons

You downloaded a CSV from a German bank export — semicolons everywhere because German Excel uses semicolon as the default. Switch to CSV → JSON, semicolon delimiter, header on. The parser handles the European convention without any special config.

Example: round-trip integrity check

Worried that your JSON-to-CSV conversion will lose data? Convert one direction, hit “Use output as input” to swap to the reverse direction, convert back. Compare with the original JSON. Any divergence is the cost of round-tripping through CSV — typically: numbers become strings, nulls become empty strings, nested objects become JSON-encoded cell text. None of those are bugs, but knowing about them lets you decide whether CSV is the right interchange format for your use case.

Common mistakes

Expecting type preservation through CSV. Numbers, booleans, and nulls in JSON all become strings or empty cells in CSV, then strings on the way back. If you need types to round-trip, pick JSON or JSONL as your interchange format, not CSV.

Pasting non-array JSON. The top level must be an array. A single object ({name: "Alice"}) won’t convert because CSV has no concept of “one row with named fields outside a table” — wrap it as [{name: "Alice"}] first.

Forgetting that the delimiter must match. A semicolon-CSV parsed with comma delimiter looks like one giant column per row. The error isn’t always loud — small files might just look weird. Set the delimiter to match your source.

Mixing line endings in the same file. The parser handles all three (\n, \r\n, \r) but mixing them in the same file is a sign of upstream corruption. Normalize before pasting if the data was edited on multiple platforms.

What this tool does not do

It doesn’t do data validation. If your JSON has weird values (very long strings, unicode edge cases, embedded control characters), the conversion is best-effort. Validate your data first if it might be malformed.

It doesn’t auto-detect the format. You pick the direction explicitly. (We could add detection — JSON starts with [ or {, CSV doesn’t — but it’s faster to just click the right tab.)

It doesn’t handle truly nested CSV (sub-tables inside cells). CSV is flat by nature; if your data is nested, use JSON or pivot to a long-format CSV with a key column.

It doesn’t infer types from CSV (every cell is a string). If you want number coercion or date parsing, do that in your application code with full knowledge of the data — guessing at the converter level introduces bugs. For JSON pretty-printing or validation before/after conversion, the JSON formatter & validator is the companion; for YAML-flavoured configs, the YAML ↔ JSON converter handles that pair.

Frequently asked questions

Why does my CSV keep all numeric values as strings after converting to JSON?

CSV has no native types — every cell is just text. When parsing CSV to JSON, the converter doesn't try to guess whether '42' is a number or a string, because guessing wrong is worse than being explicit. If you want typed values, post-process the JSON: `Number(row.score)` or use a schema validation library. The lookup table in your code can do the casting safely; this tool can't, because '01234' might be a code, not the number 1234.

What does the converter do with nested objects in my JSON array?

Nested objects and arrays are JSON.stringify'd into a single CSV cell. So a row like `{name: 'Alice', tags: ['a', 'b']}` becomes a CSV row where the tags column contains `["a","b"]` as text (with embedded quotes properly escaped). This works for round-trips: convert back to JSON and the cell is still text — you'd need to JSON.parse it manually if you want the array back. CSV isn't designed for nested data; truly nested needs a flattening step before conversion or a different format like JSONL.

Why does my converted CSV have quotes around some fields but not others?

RFC 4180 says fields must be quoted only when they contain the delimiter (comma, by default), a quote character, or a line break. Fields without those characters don't need quoting. So 'Alice' goes in unquoted but 'Smith, John' becomes `"Smith, John"` and 'she said "hi"' becomes `"she said ""hi"""` (with embedded quotes doubled). The output is the minimal RFC 4180-compliant form.

How does the converter handle rows with missing keys in my JSON?

It collects the union of all keys across all objects in first-seen order, then fills empty strings for missing values. So `[{a:1,b:2},{a:3,c:4}]` produces three columns (a, b, c) and the missing cells render as empty. This matches what most spreadsheet tools expect — heterogeneous JSON gets aligned into a regular table.

Should I use comma, semicolon, or tab as the delimiter?

Comma is the default and what most software (Google Sheets, Excel imports, pandas read_csv) expects. Semicolon is the European convention because comma is the decimal separator in many European locales — Excel in those regions defaults to semicolon. Tab (TSV) avoids most quoting problems because tabs rarely appear in data; it's the easiest format for command-line piping with awk and cut. Pipe is rare but useful when your data contains commas, semicolons, AND tabs.