How to Convert CSV to JSON Without Breaking on Quoted Commas
Most CSV-to-JSON converters work fine until a cell contains a comma. Then a naive converter splits that one cell into two columns, every value after it shifts, and you get a JSON array where half the keys are wrong. You usually don't notice until something downstream throws.
The reason is simple: CSV looks trivial and isn't. It's a quoting format pretending to be a delimiter format. The hard parts aren't the commas you can see; they're the commas, newlines, and quotes hiding inside quoted fields, plus a byte-order mark you can't see at all.
This guide walks through the cases that break naive converters, what a correct parser does instead, and which of those cases the CSV to JSON converter on codeswap handles for you versus which you still have to watch. It runs entirely client-side, so you can test your own file without uploading it anywhere.
What a correct CSV parser actually does
The closest thing CSV has to a spec is RFC 4180. The rules that matter for conversion are short:
- Fields are separated by commas. Records are separated by line breaks (CRLF in the spec, but real files use LF too).
- Any field may be wrapped in double quotes. A field must be quoted if it contains a comma, a double quote, or a line break.
- Inside a quoted field, a literal double quote is written as two double quotes (
"").
That third rule is where the hand-rolled line.split(',') approach dies. Splitting on commas assumes commas are always delimiters. Inside a quoted field they're data. A correct parser is a small state machine that tracks whether it's currently inside quotes, not a string split.
Here's the canonical failure. This is one row with three fields:
id,note,amount
1,"Paid Acme, Inc.",4200A delimiter-only parser reads four columns and produces {"id":"1","note":"Paid Acme","amount":" Inc."} plus a stray 4200 with no header. A quote-aware parser sees the opening quote, treats the comma as literal text, and gives you {"id":"1","note":"Paid Acme, Inc.","amount":"4200"}. The codeswap converter uses a quote-aware state machine, so this case is handled.
The cases that silently corrupt your output
Test any converter against these four before you trust it with real data.
1. Commas inside quoted fields. Covered above. Addresses, company names, and free-text notes are full of them. If your output has more keys than your header row, this is almost always the cause. The codeswap converter handles it.
2. Newlines inside quoted fields. A multi-line address or a comment with a line break is legal CSV as long as it's quoted, and it's still one record:
id,address
1,"12 Main St
Suite 400"Many converters, the codeswap one included, read the file line by line before parsing, so a quoted newline gets treated as a record boundary and the row breaks in half. This is the one hazard the codeswap tool does not solve for you. If your data has embedded newlines in fields, strip or replace them before converting, or use a parser built specifically for multi-line fields.
3. Escaped quotes. The doubled-quote escape trips up converters that strip quotes too eagerly. The field "She said ""hi""" should decode to She said "hi". The codeswap converter collapses the doubled quotes correctly; a lazy parser leaves dangling quotes or truncates at the first inner quote.
4. The BOM. Files exported from Excel are frequently saved as UTF-8 with a byte-order mark, the three bytes EF BB BF at the very start. It's invisible in most editors. The damage: your first header becomes id instead of id, so every lookup on that first column key fails and row.id reads undefined even though the JSON shows a value. The codeswap converter does not strip the BOM, so if your file came from Excel, remove those leading bytes before you paste. If your first JSON key looks subtly off or won't match in code, the BOM is the usual suspect.
Type inference: when "123" should become 123
CSV has no types. Everything is text. JSON has numbers, booleans, and null. Bridging that gap is a judgment call, and it's where converters differ most.
The codeswap converter has a type-inference toggle, on by default. With it on, a value matching an integer or decimal pattern becomes a real number, true and false (and their uppercase forms) become booleans, and an empty cell becomes null. That's usually what you want for an API payload or a database import. Turn it off and every value stays a string.
Aggressive inference also corrupts real data, which is exactly why the toggle matters. The classic landmines:
- Leading-zero strings. A US ZIP code like
07030or a product SKU00451becomes7030and451once coerced to a number. These are identifiers, not quantities, and must stay strings. - Large numeric IDs. A 17-digit order number exceeds JavaScript's safe integer limit of
9007199254740991(253 − 1) and silently loses precision when parsed as a number. - Ambiguous flags. A column of
Y/Nor1/0may or may not be what you want as booleans.
The rule: keep type inference off when a column holds identifiers, on when it holds genuine numeric measures. On the codeswap converter you toggle this and re-run to watch the output change, so you see exactly which cells flipped before you commit. If only a couple of columns are truly numeric, it's often safer to convert everything as strings and cast those specific fields in code, where you control precision.
From flat rows to nested JSON
A plain CSV gives you a flat array of flat objects, and that's what the codeswap converter produces: one object per row, keyed by the header. APIs often want nesting instead. There's a widely used convention for expressing structure in a flat header, dot notation in the column names, where a column named user.address.city is meant to build a user object, an address object inside it, and a city key.
Be clear about what's a convention and what's a tool feature. Dot notation is a naming convention, not part of CSV or JSON, and the codeswap CSV to JSON converter does not interpret it. Give it this header:
id,user.name,user.email,user.address.city
1,Ada,[email protected],Londonand you get flat keys with literal dots in them, "user.name" and the rest, not a nested object. To get true nesting, do it as a post-processing step: get the flat JSON correct first, then reshape it. The JSON flatten tool round-trips dotted keys, so its unflatten direction turns user.address.city into nested objects, and the jq playground lets you script an arbitrary transform and test it before you ship. Keep the two concerns separate: get the conversion right, then build structure, because it's easier to debug one thing at a time.
A workflow that avoids surprises
Putting it together, here's a sequence that sidesteps the usual problems:
- Check for a BOM and confirm the real delimiter first. Not every CSV uses commas. European exports often use semicolons; database dumps are frequently tab-separated. The codeswap converter sniffs the first line for the most common separator and lets you override it with comma, semicolon, tab, or pipe, but eyeball the first line anyway. Strip a BOM here if Excel added one.
- Paste into the CSV to JSON converter and check the row count. If the JSON array has more or fewer objects than your CSV has data rows, you have a quoting or embedded-newline problem. Find it before anything else.
- Decide type inference per use case. Identifiers as strings, measures as numbers. When in doubt, keep everything as strings and cast in code.
- Add nesting last, as a separate step, using flatten or jq on the already-correct flat JSON.
- Validate the result. Run the output through the JSON Schema validator if you have a schema, or at least eyeball it in the JSON formatter to confirm the shape.
Because everything runs in the browser, a 50,000-row export with customer PII never leaves your machine, which matters more than convenience when the file is real.
Going the other direction and adjacent tasks
The same quoting rules apply in reverse. When you flatten JSON back to a spreadsheet, any value containing a comma, quote, or newline has to be re-quoted and escaped, or you reintroduce the exact corruption this guide is about. The JSON to CSV converter handles the escaping, and JSON array to CSV covers the common array-of-objects case and flattens nested values into columns.
If your nested JSON is too deep to fit a flat CSV cleanly, flatten it into dotted keys first, then export. That's the round-trip partner of the dotted-header convention above.
Other CSV-shaped jobs that come up alongside conversion: inferring a schema from a sample to know your column types up front, viewing a large CSV as a sortable table to spot the bad row, diffing two CSV files to see what changed between exports, and converting CSV to YAML when your config tooling wants YAML. For reshaping the JSON after conversion, the jq playground is the fastest way to test a transform.
Skip the manual work. The companion tool runs this in your browser, with nothing uploaded.
CSV to JSON converterFrequently asked questions
Why does my converter split one cell into multiple columns?
The cell contains a comma and your parser is splitting on commas without respecting quotes. RFC 4180 says a field with a comma must be wrapped in double quotes, and the comma inside those quotes is data, not a delimiter. Use a quote-aware parser rather than a line-and-comma split. The codeswap CSV to JSON tool handles quoted commas correctly with a real state machine.
My first JSON key looks like "id" with a weird character. What is that?
That's a UTF-8 byte-order mark (BOM), the bytes EF BB BF that Excel and some other tools prepend when saving as UTF-8. It's invisible in most editors but attaches to your first header, so lookups on that column key fail. The codeswap converter does not strip it for you, so remove those leading bytes from the file (most editors can save without a BOM, or you can strip it in code) before converting.
Will the converter break if a field contains a line break?
It can. A newline inside a quoted field is valid CSV and should stay part of that one record, but the codeswap converter reads input line by line before parsing, so an embedded newline is treated as a record boundary and the row splits in two. If your data has multi-line fields, replace or strip those newlines first, or use a parser built specifically for multi-line CSV fields.
How do I build nested JSON objects from a flat CSV?
Not directly in this converter. Dot notation in headers like user.address.city is a common convention, but the codeswap CSV to JSON tool does not interpret it; you would get a flat key literally named "user.address.city". Do nesting as a post-processing step: convert to flat JSON first, then use the JSON flatten tool's unflatten direction or the jq playground to build the structure you need.
Should ZIP codes and IDs be converted to numbers?
No. Values like 07030 or a 17-digit order number are identifiers, not quantities. Coercing them to numbers drops the leading zero or exceeds JavaScript's safe integer limit (9007199254740991) and silently loses precision. Turn type inference off for identifier columns and on only for genuine numeric measures, or convert everything as strings and cast specific fields in code.
Is converting CSV to JSON in the browser safe for sensitive data?
On codeswap, yes. The CSV to JSON conversion runs entirely client-side in your browser, so the file is never uploaded to a server. That makes it safe for exports containing customer data or other PII, which is exactly the kind of file you don't want to paste into a random online service.