Wapgee Logowapgee

CSV ⇌ JSON converter

Paste or drop CSV and get JSON, or paste JSON and get CSV. Quoting, delimiters, headers, and types are handled in the browser. Copy or download the result, nothing is uploaded.

InputCSV · auto
JSON

Two formats, one table

CSV is what spreadsheets, exports, and data teams hand you: one record per line, fields separated by a delimiter, and a header row if you are lucky. JSON is what APIs, config files, and front-end code expect: named fields, real numbers and booleans, and nesting. Moving between them sounds trivial until a field contains a comma, a quote, or a line break, or a column of zip codes turns into integers and loses its leading zeros.

This converter goes both ways. Paste or drop a file and the direction is picked from the first character: input starting with [ or { is treated as JSON to CSV, anything else as CSV to JSON. Override it when the guess is wrong. Everything runs in your browser, with files above about 1 MB handed to a Web Worker so the tab stays responsive up to the 10 MB limit.

CSV to JSON

CSV
id,name,city,zip
1,"Ada, Countess",London,SW1A
2,Linus,Helsinki,00100
JSON (array of objects)
[
  { "id": "1", "name": "Ada, Countess", "city": "London", "zip": "SW1A" },
  { "id": "2", "name": "Linus", "city": "Helsinki", "zip": "00100" }
]

With the header option on, the first row becomes the keys of every object. Turn it off and the keys become column_1, column_2, and so on. The array-of-arrays shape skips keys altogether and gives you a plain matrix, which is smaller and convenient when you are feeding a charting library or a spreadsheet API.

Quoted fields with embedded commas, doubled quotes, and newlines inside a cell are handled by PapaParse, the same parser used by most browser-based data tools. Delimiter auto-detection covers commas, semicolons (the default in many European Excel locales), tabs, and pipes; you can also force one from the options.

Type inference, and why it is off by default

CSV has no types: everything is text. JSON does, so a converter has to decide whether 42 is a number and true is a boolean. Guessing is convenient and dangerous in equal measure. A zip code such as 02115 parsed as a number becomes 2115. A 17-digit order id becomes a floating-point approximation, because JSON numbers are IEEE-754 doubles and lose precision past 15 or 16 digits.

That is why inference is opt-in here, and why even with it on the tool refuses to coerce values with a leading zero (other than 0 itself) or more than 15 digits. When you enable it, 42 becomes a number, true and false become booleans, and empty cells become null.

The guard rails are what make a round trip safe. Convert CSV to JSON and back with the same options and the values come out equivalent; only the quoting may differ, because a field is only quoted when it has to be.

CSV
sku,qty,active,zip,order_id
A1,3,true,02115,12345678901234567
JSON with inference on
[
  {
    "sku": "A1",
    "qty": 3,
    "active": true,
    "zip": "02115",
    "order_id": "12345678901234567"
  }
]

What happens to messy files

Real exports are rarely clean, so the converter reports what it fixed instead of failing:

  • Duplicate header names get a numeric suffix, so two name columns become name and name_2 rather than one overwriting the other.
  • Empty header cells become column_N, using the original column position.
  • Short rows are padded with null for the missing fields.
  • Rows with more cells than headers keep the overflow in an _extra array instead of silently dropping data.
  • A byte-order mark at the start of the file, common in Excel exports, is stripped so the first header does not come out as id.

Each of these shows up as a notice above the output, so you know the shape of the data changed and can decide whether to fix the source.

JSON to CSV

JSON
[
  { "id": 1, "user": { "name": "Ada", "email": "ada@x.io" }, "tags": ["admin", "beta"] },
  { "id": 2, "user": { "name": "Linus" }, "tags": [] }
]
CSV with flatten on
id,user.name,user.email,tags
1,Ada,ada@x.io,"[""admin"",""beta""]"
2,Linus,,[]

An array of objects becomes one row per object, with the header built from the union of every key seen, so records with different fields line up under a shared set of columns. Nested objects are flattened to dot-notation columns such as user.name when flatten is on; arrays are kept as a JSON string in a single cell because a flat table has nowhere else to put them. An array of arrays is written as-is, and a single object becomes a one-row table.

The output options match what downstream tools expect: choose the delimiter, switch line endings to CRLF for Windows and older Excel versions, and quote every field if a strict importer needs it. The download adds a byte-order mark so Excel opens accented characters correctly.

Where it fits

  • Turning a spreadsheet export into fixture data or a seed file for a test suite, with inference on so numbers are numbers.
  • Getting an API response into Excel or Google Sheets for someone who does not read JSON, with flatten on so nested fields become columns.
  • Checking what a CSV actually contains before importing it: the row and column summary and the notices catch ragged rows and duplicate headers early.
  • Converting semicolon-delimited European exports to plain comma-separated files that a script expects.

From JSON, the JSON, YAML and TypeScript converter takes you on to a typed interface, and the Markdown table generator accepts the same CSV when the destination is a README or a pull request.

FAQ

Is my data uploaded?

No. Parsing runs in a worker in your browser, including files up to 10 MB. The CSV or JSON never leaves your device.

What is the maximum file size?

10 MB. Above about 1 MB the conversion is handed to a Web Worker so the tab stays responsive while PapaParse does the work.

Will semicolon CSVs from Excel convert?

Yes. Delimiter auto-detect picks up commas, semicolons, tabs, and pipes. You can also force a delimiter from the options row.

Why are my zip codes strings?

Type inference is off by default, so 02115 stays "02115". Turn inference on for numbers and booleans; leading zeros and 16+ digit IDs still stay strings, because JSON numbers cannot represent them faithfully.