How to convert an excel csv export to json for javascript
- Step 1Save your sheet as CSV from Excel — In Excel use File → Save As → CSV UTF-8 (Comma delimited). The 'CSV UTF-8' variant writes a BOM; the converter handles it either way. Make sure your header row has the field names you want as JS object keys.
- Step 2Drop the CSV onto the converter above — Accepts
.csv,.tsv,.txt. PapaParse auto-detects the delimiter, so even a semicolon-delimited European-Excel CSV works. The BOM is handled during parsing. - Step 3Keep Array of objects — For a JS fixture you want an array of objects — the default. The preview shows the first 1.5 KB so you can confirm keys and types before copying.
- Step 4Leave type inference on — Infer numbers, booleans, null on gives you real numbers and booleans in the fixture. Turn it off only if a column (e.g. a postal code) must stay a string everywhere.
- Step 5Pick the indent your repo prefers — 2 spaces for a readable committed fixture, Minified for a compact one. Either way the JSON is valid JavaScript array-literal syntax once assigned to a const.
- Step 6Copy or download and paste into your .js file — Copy from the preview for a small file or Download JSON for a large one, then write
const data =followed by the array, orexport const data = [...]. Save the.jsfile as UTF-8 so accented names render.
Excel CSV quirks and how the converter handles them
What Excel writes vs what you get in the JSON.
| Excel quirk | In the CSV | In the JSON output |
|---|---|---|
| UTF-8 BOM (CSV UTF-8 export) | \uFEFF before first header | Stripped during parse — first key is clean |
| Quoted numbers | "42" | 42 (number, inference on) |
| Accented names | José (UTF-8 bytes) | "José" (intact Unicode) |
| Comma inside a quoted cell | "Smith, Jr." | one string "Smith, Jr." |
| Leading-zero code | 00123 | 123 (inference on) — turn off to keep "00123" |
| Scientific notation Excel applied | 5.55E+11 | 555000000000 (number) — value already mangled by Excel |
Inference → JavaScript value
Inference is global. Off means every field is a string in the fixture.
| CSV cell | JS value (inference on) | typeof |
|---|---|---|
42 | 42 | number |
3.14 | 3.14 | number |
true | true | boolean |
null | null | object (JS null) |
1,5 (EU decimal comma) | "1,5" | string — comma is a column delimiter, not a decimal |
| `` (empty) | "" | string (or key omitted with Skip empty cells) |
Cookbook
Recipes for turning an Excel CSV into a paste-ready JavaScript fixture.
Excel CSV → const data array
ExampleDefault settings. BOM stripped, numbers typed, accented name intact — paste straight into a fixture.
Input (saved from Excel as CSV UTF-8):
\uFEFFname,age,city
José,36,Málaga
Linus,54,Helsinki
Output (array, inference on):
[
{ "name": "José", "age": 36, "city": "Málaga" },
{ "name": "Linus", "age": 54, "city": "Helsinki" }
]
// fixture.js
export const data = [ /* paste array */ ];Minified fixture for a compact file
ExampleSwitch indent to Minified for a one-line array literal.
Output (Minified):
[{"name":"José","age":36},{"name":"Linus","age":54}]
// const data = [{"name":"José","age":36}, ...];Keep a postal code as a string
ExampleA ZIP/postcode must keep its leading zeros. Turn inference off so it stays a string.
Input:
name,zip
Ada,01970
Output (inference OFF):
[ { "name": "Ada", "zip": "01970" } ]
→ with inference ON, zip would be 1970Skip empty cells for optional props
ExampleBlank cells drop their key, so optional fields are simply absent in the fixture object.
Input:
name,middle
Ada,
Linus,Benedict
Output (Skip empty cells ON):
[ { "name": "Ada" }, { "name": "Linus", "middle": "Benedict" } ]Type the fixture with json-to-typescript
ExampleFeed the converted array into the sibling tool to generate an interface for the fixture.
Array from this tool →
[ { "name": "José", "age": 36, "city": "Málaga" } ]
json-to-typescript →
interface Row { name: string; age: number; city: string; }Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
BOM glued to the first object key
HandledExcel's 'CSV UTF-8' export writes a \uFEFF BOM. A naive parse leaves it stuck to the first header, giving a key like "\uFEFFname". PapaParse handles the BOM during parsing, so the first key comes out clean. If you ever still see it, the file was double-BOM'd by another tool — re-save once from Excel.
Leading-zero code becomes a number
By designA postcode or product code 00123 matches the integer pattern and becomes 123 with inference on. For codes you must keep verbatim, turn off Infer numbers, booleans, null so every value stays a string. Inference is global — if only the code column is affected, consider keeping it as text in Excel (prefix with an apostrophe) won't survive CSV, so converting with inference off is the reliable route.
European decimal comma stays a string
ExpectedIn a comma-delimited CSV, 1,5 is two columns, not the number 1.5. If your Excel locale writes decimals with commas, export as semicolon-delimited (PapaParse auto-detects it) so 1,5 is one cell — but it still does not match the number pattern (which uses a dot), so it stays the string "1,5". Replace the decimal comma with a dot first (e.g. with csv-find-replace) if you need real numbers.
Excel already mangled a long number into scientific notation
Upstream issueExcel displays a 12+ digit number as 5.55E+11 and, worse, can store it that way. The converter parses 5.55E+11 as 555000000000 — but if Excel already rounded the original (e.g. a 16-digit credit-card-like number), that precision is gone before the CSV existed. Fix at the source: format the column as Text in Excel before entering data, or import the original as text.
Smart quotes in a text cell
PreservedCurly quotes (“ ”) that Excel autocorrected stay in the string value as-is — they are valid UTF-8 characters, not JSON-breaking. If you want straight quotes in your fixture, normalize them first with the CSV cleaner (smart-quote option) before converting.
Saved as the wrong CSV variant (ANSI, not UTF-8)
Encoding riskExcel's plain 'CSV (Comma delimited)' can save in a legacy ANSI/Windows-1252 encoding, where José becomes José bytes. The converter reads what is in the file — if the bytes are already mojibake, the JSON will contain mojibake. Re-save using 'CSV UTF-8' from Excel to fix it at the source.
Duplicate header collapses a key
OverwriteTwo columns named the same in the sheet produce one JS object key; the later wins. Rename one column in Excel before saving so both values survive in the fixture.
Free tier row/file cap
LimitFree tier caps at 2 MB / 500 rows — enough for most fixtures. A large seed dataset needs Pro (100 MB / 100,000 rows). For very large fixtures, NDJSON output plus a loader that reads line by line keeps memory low in Node.
Frequently asked questions
Why does my pasted JSON have a weird character on the first key?
That is Excel's UTF-8 BOM (\uFEFF). A naive CSV parse leaves it attached to the first header. This converter uses PapaParse, which handles the BOM, so the first key comes out clean. If you still see it, the file was BOM'd twice by another tool — re-save once from Excel as CSV UTF-8.
How do I get real numbers in my fixture instead of quoted strings?
Keep Infer numbers, booleans, null on (the default). Excel stores numbers as quoted strings in CSV; inference converts "42" back into the number 42 and "true" into a boolean, so your const data array has real typed values.
Will accented or non-ASCII names survive?
Yes. Names like José, Müller, and Ångström are preserved as proper Unicode in the JSON, provided the CSV was saved as UTF-8 (Excel's 'CSV UTF-8' option). Save your .js file as UTF-8 too so they render in source.
How do I keep a postcode or product code with leading zeros?
Turn off type inference so codes like 00123 stay the string "00123". The trade-off is that genuinely numeric columns also become strings — for a mixed file, either accept that or convert the code column to a clearly non-numeric form before exporting.
My European Excel uses commas for decimals — what happens?
In a comma-delimited CSV, 1,5 reads as two columns. Export semicolon-delimited (auto-detected) so it is one cell, but 1,5 still stays a string because the number pattern expects a dot. Replace the decimal comma with a dot using csv-find-replace before converting to get real numbers.
Is my spreadsheet data uploaded?
No. PapaParse parses and the JSON is built in your browser. The spreadsheet's contents never reach a JAD Apps server. Only an anonymous run counter is stored when signed in, and you can opt out.
Can I paste the output straight into a .js file?
Yes. The array is valid JavaScript array-literal syntax once you assign it: const data = [ … ] or export const data = [ … ]. No JSON.parse wrapper is needed because JSON is a subset of JS object literal syntax.
Why did a long number turn into scientific notation?
Excel does that, not the converter. Excel may display and even store a 12+ digit number as 5.55E+11, and can round numbers beyond 15 digits. The converter parses the value it finds; fix it upstream by formatting the column as Text in Excel before entering the data.
Can I generate a TypeScript type for the fixture?
Yes — run the converted array through json-to-typescript to get an interface, or json-to-zod for a Zod schema if you validate the fixture at runtime.
What about smart quotes Excel inserted?
They are preserved as valid Unicode characters in the string — they do not break JSON. If you want straight quotes in your fixture, run the CSV through the cleaner's smart-quote normalization before converting.
How big a fixture can I convert?
Free: 2 MB / 500 rows. Pro: 100 MB / 100,000 rows. Pro+Media: 500 MB / 500,000 rows. Developer: 5 GB, no row cap. For large datasets use NDJSON output and a line-by-line loader to keep Node memory low.
Can I convert a real .xlsx directly instead of saving to CSV first?
This tool takes CSV/TSV/TXT. To convert a native Excel workbook without saving to CSV, use the sibling excel-to-json tool, which reads .xlsx directly.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.