Tool
JSON to CSV and CSV to JSON converter
Convert JSON to CSV and CSV back to JSON in your browser — nested objects flatten to dot paths, field unions with conflict-safe naming, formula-injection-safe export, file upload and table preview.
Input and options
Processing: conversion runs entirely in this browser tab — pasted text and uploaded files are never sent, stored or written into links. Closing the tab discards them.
Conversion result
Conversion rules
JSON → CSV. The input may be an array of objects, a single object (one output row), or a container holding an array such as {"data":[…]} — the first object array is used and reported. Nested objects flatten into dot paths (user.name); arrays serialize as JSON strings unless Expand arrays is on (tags.0, tags.1). Fields form the union across all records in first-seen order; missing fields stay empty cells, null exports as an empty cell, and non-object array elements are skipped with a warning — never silently.
When two sources want the same column name — e.g. a literal key "a.b" versus the expanded path a.b, or duplicate generated names — the later column is renamed a.b#2, #3… and every rename is listed in the warnings. Data is never overwritten or merged. Cells whose text starts with = + - @ or a tab are prefixed with ' by default, so Excel and Sheets display them as text instead of evaluating them as formulas; cells longer than 32,767 characters are truncated (Excel's limit) and counted.
CSV → JSON. Quoted commas, double quotes ("") and embedded newlines are handled per RFC 4180, and the delimiter can be auto-detected or fixed (comma, semicolon, tab, pipe). With header on, the first row names the fields — empty cells become column_N and duplicates name#2. Rows with a different column count are warned about: surplus cells land in extra_N fields, missing ones stay empty strings. With header off, the output is an array of arrays. Values stay strings by default, preserving IDs and leading zeros like 007; the optional type inference only converts canonical numbers, true/false and null — 007, +5 and padded values never turn into numbers.
Files up to 8 MB are read locally; inputs over ~400 KB convert in a background worker so the page stays responsive. Paste is limited to 2,000,000 characters. Nothing is uploaded — see our related tools: JSON structural diff, curl to Python/JS converter, log redaction tool.
FAQ
What JSON shapes are accepted?
An array of objects is the canonical input. A single object converts to a one-row sheet, and a container like {"data":{"items":[…]}} unwraps automatically — the first array of objects is used and the path is shown in the result. Non-object elements inside the array are skipped with a warning, never silently dropped.
How are nested objects and arrays turned into columns?
Nested objects flatten into dot paths such as user.name or user.addr.city. Arrays serialize as compact JSON strings by default so nothing is lost; enabling 'Expand arrays' maps them to index columns like tags.0 and tags.1 instead. Field names form the union across all records, ordered by first appearance — you can then deselect or reorder columns before downloading.
Two columns want the same name — what happens?
The collision is resolved deterministically and loudly: the first column keeps the name and later ones are renamed to name#2, name#3…, each listed in the warnings. This covers literal keys containing dots ("a.b" vs expanded a.b), duplicate generated names and repeated CSV headers — nothing is silently overwritten or merged.
Why are some cells prefixed with an apostrophe?
That is the formula-injection guard. Text starting with =, +, -, @ or a tab is evaluated as a formula when the CSV is opened in Excel or Google Sheets — a real abuse vector for untrusted data. The tool prefixes those cells with ' so they display as text, counts how many were escaped, and lets you turn the guard off in options.
Does CSV → JSON change my value types?
Not by default: every field stays a string, so IDs, phone numbers and leading zeros like 007 survive intact. The optional type inference only converts canonical numbers, true/false and null — 007, +5, ' 8 ' and 0x10 remain strings. Quoted commas, "" escapes and embedded newlines are parsed per RFC 4180.
Is my data uploaded or stored?
No. Parsing and conversion run inside this browser tab — large inputs go to a same-origin Web Worker — and nothing is sent to a server, stored, or written into a URL. Closing the tab discards everything.