Convert JSON to CSV in JavaScript: Papa.unparse vs Papa.parse
Papa.unparse writes CSV from JavaScript objects. Papa.parse reads CSV into objects. They are not inverses once numbers, nested values, or typing are involved. The live JSON to CSV page runs JSON.parse then Papa.unparse. For example, a JSON array with name, age, email, and city columns produces CSV like name,age,email,city then John Doe,30,john@example.com,New York (CRLF). Download output is converted.csv as text/csv. Nested objects and arrays are JSON.stringify'd so a cell is not [object Object]: Ada plus {city:NY} writes Ada,"{""city"":""NY""}". JSON.parse("1e16") is 10000000000000000; unparse writes that number. 1e-324 writes 0. 9007199254740993 writes 9007199254740992. On CSV to JSON, a two-column cell 1e16,foo stays the string "1e16" because Papa's FLOAT test requires parseFloat < 2^53. That page calls Papa.parse, not unparse. Not Excel, not a flattener, not NDJSON. Nothing is uploaded.
Papa Parse exposes two different functions. parse turns delimited text into rows. unparse turns rows into delimited text. Docify splits those APIs across two pages so each output is honest. This guide names what JSON to CSV writes after JSON.parse, why a nested value becomes a quoted JSON string, and why the same digit sequence is a number on one page and a string on the other.
Two Papa APIs, two pages
unparse writes CSV; parse reads it
Papa's docs treat unparse as the writer for an array of objects (or an array of arrays). Default newline is CRLF. Default delimiter is comma. The live JSON page passes columns as the first-seen union of Object.keys, so a later extra key still becomes a header. [{"name":"Ada","age":30},{"name":"Bob","city":"NY"}] writes name,age,city then Ada,30, and Bob,,NY. A missing later key is an empty field: Ada,30 then Bob,. null is an empty field. true / false write true / false. A string with a comma, quote, or LF is RFC 4180 quoted; an inner quote is doubled (hel"lo → "hel""lo").
Conversion happens on click
On the JSON to CSV page, paste or type JSON into the input box and click Convert. The page calls JSON.parse followed by Papa.unparse to produce CSV with CRLF line endings. Download saves the result as converted.csv with MIME type text/csv. You can also upload a .json or .txt file, which reads the file with FileReader.readAsText and fills the JSON input. Nothing is uploaded to a server.
Nested cells are JSON strings
Raw unparse writes [object Object]
CSV has no native nested object type. Papa.unparse stringifies each cell using the host ToString method, so an object would become the unhelpful string [object Object]. To preserve nested data, the JSON to CSV page runs JSON.stringify on any non-null object or array before calling unparse. This keeps the nested structure as valid JSON text within the cell. For example, a row with name "Ada" and a nested {city:"NY"} object produces Ada,"{""city"":""NY""}" — the inner quotes are doubled per RFC 4180. If you later parse that CSV back with Papa.parse, the cell comes back as a string, not a nested object.
IEEE-754 happens before unparse
1e16 is already 10000000000000000
JSON.parse uses IEEE-754 binary64 (ECMA-262 / RFC 8259 §6). Exact integers end at 9007199254740991 (2^53 − 1). JSON.parse("1e16") is 10000000000000000; Papa.unparse writes that decimal. JSON.parse("1e-324") is 0 (underflow). JSON.parse("9007199254740993") is 9007199254740992. Quoted "9007199254740993" stays the exact string. This is not BigInt.
Papa.parse keeps 1e16 as a string
The reverse page, /csv-to-json/, calls Papa.parse with header, skipEmptyLines, and dynamicTyping. Papa's FLOAT test requires parseFloat to be strictly inside ±2^53. A two-column output n,x plus 1e16,foo stays {"n":"1e16","x":"foo"}. Write 1e15 for the number 1000000000000000. A cell 9007199254740992 stays a string; 9007199254740991 becomes a number. 1e-324 becomes 0 on both pages (underflow is inside ±2^53). The two outputs are not a round trip.
What Convert rejects
One object is a row; NDJSON is not
After JSON.parse, an array of objects is kept. One object is wrapped as a one-row array: {"name":"Ada","age":30} writes name,age then Ada,30. [] and {} write an empty string (no header). Array of primitives such as [1,2,3], array of arrays, and JSON Lines / NDJSON fail. JSON.parse rejects a second value after the first object. Duplicate names keep the last parse value (RFC 8259 §4). Papa's unparse can write an array of arrays; this page does not accept that shape. Not Excel.
Convert objects with Papa.unparse
Example: Convert returns the four-column John Doe table. Nested values stay JSON strings. Nothing is uploaded.
Use JSON to CSV →FAQ
- What is the difference between Papa.parse and Papa.unparse?
- Papa.parse converts CSV to JavaScript objects. Papa.unparse converts objects back to CSV.
- Does Papa.parse auto-detect delimiters?
- Yes. It detects commas, semicolons, tabs, and other common delimiters automatically.
- How are headers handled?
- With header: true, the first row becomes object keys. Otherwise rows are arrays.
- Does this tool upload my data?
- No. All parsing runs in your browser using Papa Parse. Nothing is sent to a server.
Related
- CSV to JSON in the Browser with Papa Parse
- How to Format JSON Online: Parse and Prettify
- JSON vs YAML: Configuration Files
- Try the live JSON to CSV converter to transform your JSON arrays into downloadable CSV files.
- Live tools: CSV to JSON · JSON formatter