What the parser actually does
This CSV to JSON converter reads your rows with a full RFC 4180 parser in the browser and gives back
either an array of objects keyed by the header row, or an array of arrays. Quoted commas survive,
doubled quotes collapse to one, newlines inside a cell stay inside that cell, and \r\n, \n and a
lone \r all end a record.
Nothing is uploaded. That matters more here than for most converters, because the file people paste into a CSV tool is usually an export of something real — a customer list, an order log, a payroll run.
Why split(',') is the wrong answer
It is the first thing everyone writes, and it is wrong for a reason that will not show up in your
test fixture. In CSV, a comma inside double quotes is a character, not a boundary. So the moment a
row contains "Ada, Countess", splitting produces two fields where there is one, every later column
shifts, and the row lands in the wrong shape.
Two more rules break the same shortcut. A quote inside a quoted field is written twice, so
"He said ""hi""" is a single value that contains one pair of quotes. And a quoted field may contain
a line break, which destroys the assumption that one line is one record — a file where three
addresses have a second line will parse as three extra rows, and the count will look plausible.
The correct approach is a character-by-character state machine with one bit of memory: are we inside quotes? It is about forty lines, it never guesses, and it is what runs on this page.
Types, and the fields that only look numeric
Converting "36" to 36 is usually what you want. Converting "007" to 7 never is.
The rule used here is strict on purpose: a value becomes a number only if it matches what the JSON specification itself calls a number. That excludes leading zeros, a leading plus, a trailing dot, a comma used as a decimal mark and anything with surrounding whitespace. The practical effect is that postcodes, phone numbers, account codes, ISBNs and SKUs stay as strings, which is the only correct outcome — they are identifiers that happen to be written with digits.
Booleans are recognised in any case, because spreadsheets export TRUE and FALSE in capitals.
yes and no are left alone, since they are ordinary answers in a survey export as often as they
are flags.
Empty cells are the one genuinely ambiguous case, so they get their own toggle. An empty string is
honest about what the file contains; null is more useful when the JSON goes into a database that
distinguishes missing from blank.
The header row, and what happens without it
With the header toggle on, the first record becomes the keys. Blank header cells are named
column_2 and so on by position, and a repeated name gets a _2 suffix instead of quietly
overwriting the earlier column — a duplicate id in a joined export is common and losing one of
them is not acceptable.
With it off, every record is data and every key is generated. That is the right setting for a file that was already stripped of its header, and for the fragment you pasted out of the middle of a larger file.
Ragged rows are padded rather than rejected, and the extra values are kept under generated names.
Seeing column_9 appear in your output is a signal worth chasing: it usually means an unescaped
quote somewhere above, which has merged two records into one.
Going the other way, the JSON to CSV converter applies the same quoting rules in reverse and flattens nested objects into dotted columns. If what you actually want is a table to paste into a README or a pull request, the Markdown table generator takes the same pasted rows.