Splitting a CSV line on commas works until a field contains a comma. RFC 4180 handles this by letting a field be wrapped in double quotes, with any literal quote inside it doubled:
name,note Ada,"Works on Tuesdays, sometimes Thursdays" Bob,"He said ""hi"" first"
A converter that calls split(',') on each line cuts the first row into three fields instead of two and mangles the escaped quote in the second. To get it right you walk the string character by character and track whether you're inside a quoted field. That's a small state machine. A split won't do it.
Every value comes back as a string, on purpose
A naive converter sees a cell like 501 and decides it's a number. For a US zip code that guess is wrong. 00501 (Holtsville, NY) loses its leading zeros as soon as it's coerced, and a five-character string becomes a three-digit integer. The safer default leaves every field as the string it is in the CSV and lets you decide downstream whether "501" should be a number. Type coercion guesses wrong about as often as it guesses right.
Header row rules
The first row is treated as column names. A header with an empty column name (two commas in a row, as in name,,email) is rejected outright instead of silently creating a field called "". An empty name almost always means the header row itself is malformed.
Going the other way: JSON to CSV expects flat objects
In the other direction, the input has to be a JSON array of objects. A single object or an array of arrays won't work. Any value that isn't a plain string, number, boolean, or null gets JSON.stringify'd into its one cell instead of being flattened into separate columns:
[{ "id": 1, "tags": ["a", "b"] }]
↓
id,tags
1,"[""a"",""b""]"That's a deliberate scope limit. Some CSV tools flatten nested structure into dotted column names (address.city, address.zip), but doing so means assuming which nesting pattern you want, and that assumption doesn't hold for every shape. If you need every record flattened the same way, look at the output before writing off the tags column. It's valid JSON, sitting inside one CSV cell.