Convert

CSV to JSON Converter

Convert a CSV file into a JSON array of objects, keyed by your headers. Runs in your browser — no upload, no signup.

Most CSVs end up needing to be JSON eventually — to seed a database, mock an API, feed a frontend, or hand to whatever tool only speaks JSON. This converter does that one job and does it predictably: each row in the CSV becomes one object in a JSON array, with the header row as the keys. No nesting tricks, no schema-guessing, no surprises.

Output is pretty-printed JSON (indented two spaces) so it's diff-friendly and readable. The same parser SheetCompare uses for spreadsheet diffs reads your CSV, so quoting, escaping, and edge cases like embedded newlines work correctly. Everything happens client-side — your file is never uploaded.

How it works

Three steps, no signup

  1. 1

    Drop your CSV

    Drag a .csv file into the box above, or click to pick one. Files with quoted fields, embedded newlines, and UTF-8 content all work.

  2. 2

    We map rows to objects

    Row 1 becomes your JSON object keys. Each subsequent row becomes one object in the output array. Cell values come through as strings — no aggressive type-guessing.

  3. 3

    Download the .json

    Download a pretty-printed JSON array. Drop it straight into your code, paste it into a seed file, or hand it to your API.

FAQ

Frequently asked questions

What does the output JSON look like?
A JSON array of objects. If your CSV has columns `name,email,age`, you get `[{"name": "...", "email": "...", "age": "..."}, ...]`. Pretty-printed with two-space indentation. Not NDJSON (newline-delimited) — if you need that, paste the array into `jq -c '.[]'` or similar after downloading.
Are numbers and booleans converted, or do I get strings?
You get strings. CSV has no type system — "123" and "true" are just text in the source file, and we don't guess. This is intentional: silent type coercion is the single biggest source of CSV-to-JSON bugs (zip codes losing leading zeros, account numbers becoming floats, the string "NaN" turning into a number). Cast types in your code where you actually know the schema.
How are empty cells represented?
As empty strings (`""`), not as `null`. The CSV spec doesn't distinguish between "no value" and "empty string," so we don't either — preserving the source verbatim is safer than guessing intent. If you need `null` for empties, run the output through a quick `JSON.stringify(JSON.parse(json), (k, v) => v === "" ? null : v)` after downloading.
What if my CSV has no header row?
The first data row is treated as the header row and consumed as keys. If you don't want that, add a synthetic header row (`col1,col2,col3,...`) before converting. CSV without headers is ambiguous — there's no way for a tool to know the difference between "row of data that looks like headers" and "actual headers."
What happens with duplicate header names?
Later columns with duplicate names overwrite earlier ones in each row's object — that's how JavaScript objects work, and we don't try to disambiguate. If your CSV has two columns both named `id`, only the rightmost `id` value will be in the output. Rename the duplicate columns in your source before converting if you need them both.
Can I get nested JSON instead of a flat array?
Not from this tool. CSV is fundamentally tabular — it has no way to express nesting — so any nesting we produced would be guesswork (split by dot? underscore? bracket?). For nested output, post-process the flat array in your code where you know the schema, or use a tool purpose-built for hierarchical CSV like csvjson with explicit options.
What encoding is the output?
UTF-8. JSON is required by spec to be Unicode (UTF-8 is the standard transport encoding), so non-ASCII characters in your CSV — accented letters, CJK, emoji — pass through cleanly. The downloaded file has no BOM.

Need to compare two files?

Drop two spreadsheets and see every change in seconds. Free, private, runs in your browser.