JSON to CSV Converter
Convert JSON arrays to CSV format and back. Auto-detect columns, flatten nested objects, preview as a table, and download as a .csv file.
This tool converts JSON arrays into CSV format and CSV back into JSON. It auto-detects column headers from object keys, flattens nested objects using dot notation, and lets you choose between comma, tab, or semicolon delimiters per RFC 4180. Preview the result as a table before downloading as a .csv file. Everything runs in your browser, so sensitive data never leaves your machine.
About JSON to CSV Converter
How JSON Maps to CSV
A JSON array of objects maps one-to-one onto a CSV table: each object becomes a row and each unique key becomes a column header. The converter collects the union of keys across every object, so rows missing a key get an empty cell rather than a crash.
| JSON Structure | CSV Result | Notes |
|---|---|---|
| [{"name": "Alice", "age": 30}] | name,age\nAlice,30 | Direct mapping - keys become headers |
| [{"a": 1}, {"a": 2, "b": 3}] | a,b\n1,\n2,3 | Missing keys become empty cells |
| [{"addr": {"city": "NYC"}}] | addr.city\nNYC | Nested objects flattened with dot notation |
| [{"tags": ["a","b"]}] | tags\n["a","b"] | Arrays kept as JSON strings |
Worked example: take the array [{"name":"Alice","age":30,"address":{"city":"Portland","state":"OR"}},{"name":"Bob","age":28,"address":{"city":"Seattle","state":"WA"}}]. The flattener produces keys name, age, address.city, address.state. The CSV output is four columns and two data rows: name,age,address.city,address.state followed by Alice,30,Portland,OR and Bob,28,Seattle,WA. No data loss, no re-encoding needed.
What Does RFC 4180 Say About CSV?
RFC 4180 is the informational specification that standardises the CSV format, published by the IETF in October 2005 and still the reference most libraries follow today. It defines a record-per-line text file using CRLF terminators, a header row, commas as field separators, and double quotes as the escape character. Fields containing commas, newlines, or double quotes must be wrapped in double quotes, and embedded double quotes are escaped by doubling them.
| Situation | Rule | Example |
|---|---|---|
| Field contains delimiter | Wrap in double quotes | "London, UK" |
| Field contains newline | Wrap in double quotes | "Line 1\nLine 2" |
| Field contains double quote | Escape by doubling, wrap in quotes | "He said ""hello""" |
| Field has leading/trailing spaces | Wrap in quotes to preserve | " spaced " |
| Normal field | No quotes needed | Alice |
The spec registers the media type text/csv with two parameters: charset (default US-ASCII, but UTF-8 is the pragmatic modern default) and header (present or absent). Most spreadsheet applications ignore the strict CRLF requirement and happily read LF-terminated files, which is why this converter writes plain LF for portability.
How Are Nested Objects Flattened?
Nested objects are flattened by concatenating parent and child keys with a dot separator, so {"user":{"address":{"city":"London"}}} becomes the single column user.address.city. This is the same convention used by tools like jq --recurse, pandas json_normalize, and the MongoDB $unwind pipeline.
| Nested JSON Key Path | CSV Column Header | Example Value |
|---|---|---|
| user.name | user.name | Alice |
| user.address.city | user.address.city | London |
| user.address.postcode | user.address.postcode | SW1A 1AA |
| metadata.created | metadata.created | 2026-04-06 |
Arrays inside objects stay as JSON strings in a single cell (e.g. ["tag1","tag2"]) because CSV has no native list type. If you need one row per array element, either pre-process the JSON with jq '.[] | {id, tag: .tags[]}' or post-process the CSV in Python with df.explode('tags'). Dot notation is also ambiguous when a key itself contains a literal dot - in that case rename the key before converting.
Which Delimiter Should You Use?
Pick the comma for maximum compatibility, a tab for pasting directly into a spreadsheet, and a semicolon for European locales where the comma is the decimal mark. Tab-separated values (TSV) are defined by IANA media type text/tab-separated-values and predate CSV - they avoid the quoting dance because tabs rarely appear in user-entered data.
| Delimiter | Character | Best For |
|---|---|---|
| Comma | , | Default CSV. Universal support in spreadsheets and databases. |
| Tab | \t | Pasting directly into Excel or Google Sheets. Avoids issues with commas in data. |
| Semicolon | ; | European locales where the comma is the decimal separator (e.g. 1.234,56 in Germany). |
Microsoft Excel is the big wrinkle here: on a machine with a non-English locale, Excel reads the Windows list separator from Regional Settings rather than assuming comma. That is why a CSV that opens fine in the US ends up in one column in Germany. Writing a sep=; line as the first line of the file is a long-standing Excel-specific workaround, but a cleaner fix is to pick the right delimiter up front.
Converting CSV Back to JSON
The reverse direction treats the first row as column headers and each subsequent row as an object. The parser respects RFC 4180 quoting, so commas inside quoted fields are not treated as delimiters and doubled double quotes collapse back to a single quote.
| CSV Input | JSON Output |
|---|---|
| name,age\nAlice,30\nBob,25 | [{"name":"Alice","age":30},{"name":"Bob","age":25}] |
| label,note\n"Paris, FR","Has ""comma"" inside" | [{"label":"Paris, FR","note":"Has \"comma\" inside"}] |
CSV carries no type information, so this converter applies a light heuristic: the strings true and false round-trip to booleans, null becomes JSON null, and fields that parse cleanly as numbers become numbers. Everything else stays a string. Locale-formatted numbers like 1,234.56 or 1.234,56 are left as strings because guessing the locale is riskier than leaving it to your downstream code.
Common JSON-to-CSV Scenarios
| Source | Typical JSON Shape | Tip |
|---|---|---|
| REST API response | {"data": [...]} | Extract the array from the wrapper before converting |
| MongoDB export | [{"_id": {"$oid": "..."}, ...}] | Nested _id flattens to _id.$oid column |
| Firebase Realtime DB | {"key1": {...}, "key2": {...}} | Convert object-of-objects to array first (Object.values) |
| GraphQL response | {"data": {"users": {"edges": [...]}}} | Navigate to the array node before converting |
| NDJSON (log streams) | One JSON object per line | Wrap the file in [...] with commas between lines |
| CloudWatch / Datadog logs | Deeply nested metadata | Pick the fields you need with jq first to avoid 200-column CSVs |
CSV vs TSV vs JSON vs Parquet
CSV is the smallest and most portable tabular format, but it loses types and cannot represent nesting. JSON preserves types and nesting but is roughly 2-3x larger for the same data because of repeated keys. Parquet is the column-oriented format that now dominates analytics pipelines (used by Apache Spark, DuckDB, and AWS Athena) - it stores typed columns with compression and is typically an order of magnitude smaller than gzipped CSV for the same dataset.
| Format | Types | Nesting | Size | Best For |
|---|---|---|---|---|
| CSV | All values are strings | None | Smallest text format | Spreadsheets, simple ingests, flat data |
| TSV | All values are strings | None | Similar to CSV | Pasting into spreadsheets, tab-safe data |
| JSON | Strings, numbers, booleans, null | Unlimited | 2-3x larger than CSV | APIs, complex structures, config files |
| NDJSON | Same as JSON | Unlimited | Same as JSON | Streaming logs, line-oriented processing |
| Parquet | Typed columns | Nested (struct, list) | ~10x smaller than CSV when compressed | Big data, analytics, Spark/DuckDB |
Performance and File Size Expectations
Browser JSON parsing is fast but not free. JSON.parse typically handles around 100-200 MB/s on modern V8, and the parsed object graph takes roughly 2-3x the raw string size in memory because of object headers and UTF-16 string storage. A 100 MB JSON file can therefore push 300 MB of heap before you even start converting to CSV. Chrome and Firefox both cap a single tab at 4 GB, which is plenty for most exports but not for unbounded log dumps.
| Input JSON Size | Typical Rows | Parse Time | Memory Peak |
|---|---|---|---|
| 1 MB | ~5,000 | under 50 ms | ~3 MB |
| 10 MB | ~50,000 | ~100-200 ms | ~30 MB |
| 100 MB | ~500,000 | ~1-2 s | ~300 MB |
| 500 MB+ | ~2.5M+ | 5s+, may freeze tab | 1.5 GB+ |
For anything over 100 MB, a streaming parser on the server side (Node's stream-json, Python's ijson, or jq --stream) is the right answer. Browser tools like this one are best for the 99% case where the file fits comfortably in a single parse.
Common Mistakes to Avoid
- Passing a single object instead of an array.
{"name": "Alice"}is valid JSON but has no rows. Wrap it in[...]. - Mixed-shape arrays. If half the objects have a
phonekey and half do not, the CSV will still be valid but every other row will have empty cells. That is by design - just be aware of it. - Excel mangles long numeric IDs. Strings like
"01234"or"9200000001234567"open as numbers by default, losing leading zeros or precision. Prepend a single quote or import the column as text. - Newlines inside fields open in one cell per line. RFC 4180 allows this as long as the field is quoted, but some older tools still split on any newline. Strip newlines if your downstream tool is fussy.
- BOM characters. Files exported from Excel on Windows often start with a UTF-8 byte-order mark (
0xEF 0xBB 0xBF). Some JSON parsers trip over it - strip the first three bytes before parsing if you see a mysterious "unexpected token" error.
To validate or pretty-print JSON before converting, use the JSON Formatter. For YAML input, the YAML to JSON Converter handles the translation. If your data is XML, the XML to JSON Converter is the starting point. All processing here runs in your browser - your data never leaves your machine.
Sources
- IETF RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files
- IETF RFC 8259 - The JavaScript Object Notation (JSON) Data Interchange Format
- IANA - text/tab-separated-values Media Type Registration
- ECMA-404 - The JSON Data Interchange Syntax
- Apache Parquet - File Format Documentation
- MDN Web Docs - JSON (JavaScript Reference)
- Microsoft Learn - Excel CSV Import and List Separator Behaviour
Frequently Asked Questions
What JSON structure does this converter expect?
The converter expects a JSON array of objects, where each object represents a row. The keys of the objects become CSV column headers. For example, [{"name":"Alice","age":30},{"name":"Bob","age":25}] produces a CSV with "name" and "age" columns. If different objects have different keys, all keys are collected and missing values appear as empty cells.
How does the converter handle nested objects?
Nested objects are flattened using dot notation. For example, if an object contains {"address":{"city":"NYC","zip":"10001"}}, the converter creates columns named "address.city" and "address.zip" with their respective values. Arrays within objects are converted to their JSON string representation.
Can I change the delimiter from commas to something else?
Yes. The tool supports three common delimiters - commas, tabs, and semicolons. Select your preferred delimiter before converting. Tab-delimited output is useful for pasting directly into spreadsheet applications, while semicolons are common in regions where commas are used as decimal separators.
Can I convert CSV back to JSON?
Yes. The tool is fully bidirectional. Paste CSV content into the CSV pane and click "CSV to JSON" to get a JSON array of objects. The first row of the CSV is treated as column headers, and each subsequent row becomes an object with those headers as keys.
Is my data sent to a server?
No. All conversion happens entirely in your browser using JavaScript. Your data never leaves your machine, so it is safe to convert files that contain sensitive or proprietary information.
Related Tools
Link to this tool
Copy this HTML to link to this tool from your website or blog.
<a href="https://toolboxkit.io/tools/json-to-csv-converter/" title="JSON to CSV Converter - Free Online Tool">Try JSON to CSV Converter on ToolboxKit.io</a>