How to convert json to csv for quickbooks / xero import
- Step 1Gather your transaction JSON — This can be a Stripe export, POS API feed, or any JSON list of transactions. Drop the file onto the converter above. Free files cap at 2 MB.
- Step 2Extract the array if it sits under a key — If transactions are wrapped like
{ "data": [...], "meta": {...} }, extract$.datafirst with json-path-extractor so you get one row per transaction rather than a single wide row. - Step 3Keep flattening on — Flatten nested objects (default) gives you
customer.name,line.account, etc. as separate columns you can map to the import template. - Step 4Set the delimiter for your books — Comma for standard QuickBooks/Xero CSV import; Semicolon for European Excel and locales where commas are decimal separators.
- Step 5Convert and map to the template — Click Convert to CSV. The generated headers are your JSON keys, not QuickBooks/Xero's required names — map them in your spreadsheet, or rename the JSON keys first with json-key-renamer to match
Date,Amount,Description. - Step 6Download the Excel-Ready CSV and import — Use Excel-Ready CSV (BOM + CRLF) so encoding is correct, then import via QuickBooks (Banking → File upload) or Xero (Business → Bank accounts → Import). Map columns to fields in the import wizard.
What the converter does vs what the ledger needs
The tool flattens and serialises; column mapping to the accounting template is a separate step.
| Need | Does this tool do it? | How |
|---|---|---|
| Flatten nested JSON to columns | Yes | Dot-notation, flattening on by default |
Rename to Date / Amount / Description | No | Rename JSON keys first with json-key-renamer, or map in the import wizard |
| Format Unix timestamps as dates | No | Convert in your spreadsheet before import |
| Scale smallest-unit amounts (cents) | No | Divide in your spreadsheet (=amount/100) |
| EU-locale delimiter | Yes | Switch delimiter to Semicolon |
Delimiter and download by destination
Pick the delimiter and download style for your accounting platform.
| Destination | Delimiter | Download |
|---|---|---|
| QuickBooks (US/UK) | Comma | Excel-Ready CSV |
| Xero | Comma | Excel-Ready CSV |
| European-locale Excel / books | Semicolon | Excel-Ready CSV |
| Paste into Google Sheets first | Tab | Download CSV |
Cookbook
Transaction JSON and the CSV produced, plus the mapping step for QuickBooks / Xero. Data anonymised.
Transactions flattened for mapping
ExampleNested customer and amount fields become columns; you then map them to the ledger template.
Input:
[ { "date":"2026-06-01", "amount":49.00, "customer":{"name":"Ada Co"} } ]
Output CSV:
date,amount,customer.name
2026-06-01,49,Ada Co
Map: date→Date, amount→Amount, customer.name→Description.Rename keys to match the template first
ExampleRenaming JSON keys before conversion produces headers QuickBooks/Xero accept directly.
After json-key-renamer (date→Date, amount→Amount):
[ { "Date":"2026-06-01", "Amount":49.00, "Description":"Ada Co" } ]
Output CSV:
Date,Amount,Description
2026-06-01,49,Ada CoSemicolon delimiter for European books
ExampleEU Excel treats commas as decimals, so a comma CSV merges into one column. Semicolon keeps amounts separate.
Input:
[ { "Date":"01/06/2026", "Amount":"49,00" } ]
Delimiter = Semicolon:
Date;Amount
01/06/2026;"49,00"Smallest-unit amounts need scaling
ExampleIf your source (e.g. Stripe) uses cents, the converter keeps 4900 — scale it in the spreadsheet before import.
Input:
[ { "amount":4900, "currency":"usd" } ]
Output CSV:
amount,currency
4900,usd
In Excel: =amount/100 → 49.00 before import.Optional tax field kept aligned
ExampleOnly one transaction has tax; the union header keeps the column with an empty cell for the other.
Input:
[
{ "Date":"2026-06-01", "Amount":49 },
{ "Date":"2026-06-02", "Amount":20, "Tax":4 }
]
Output CSV:
Date,Amount,Tax
2026-06-01,49,
2026-06-02,20,4Errors 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.
Headers don't match QuickBooks/Xero template names
By designThe converter uses your JSON keys as headers; it does not rename them to Date/Amount/Description. Rename JSON keys first with json-key-renamer, or map columns in the platform's import wizard.
Amounts are 100x too large
By designIf the source stores amounts in cents, the converter keeps them verbatim (no scaling). Divide by 100 (or the currency's unit) in your spreadsheet before import to avoid posting wrong figures.
Dates as Unix epochs, not DD/MM/YYYY
By designThe converter does not parse dates. Epoch integers and ISO strings pass through unchanged — convert them to your platform's expected date format in the spreadsheet first.
EU Excel merges everything into one column
SupportedEuropean Excel treats the comma as a decimal separator. Switch the delimiter to Semicolon so amounts and fields land in separate columns.
Transactions wrapped in an envelope
By designA { "data": [...], "meta": {...} } shape collapses to one wide row. Extract $.data first with json-path-extractor for one row per transaction.
Line items as a nested array
Not expandedInvoice line items as an array stay in one cell. For one row per line (needed by some import templates), extract the line-items path and convert it separately.
File over the free 2 MB limit
BlockedFree conversions cap at 2 MB / 500 rows. A full ledger export usually needs Pro (100 MB / 100,000 rows) or splitting by period.
Invalid JSON from a partial export
Invalid JSONTruncated exports error with Invalid JSON. Re-export the complete file; validate with json-validator if unsure.
Frequently asked questions
Does this tool rename columns to QuickBooks/Xero field names?
No. It flattens JSON using your original keys as headers. To match Date/Amount/Description, rename the JSON keys first with json-key-renamer, or map columns in the platform's import wizard.
Why are my amounts 100x too high?
The source likely stores them in the smallest unit (cents). The converter does no scaling to keep values exact. Divide by 100 in your spreadsheet before importing to your ledger.
How do I get the dates into the right format?
The converter passes dates through unchanged — it does no parsing. Convert Unix epochs or reformat ISO dates in your spreadsheet to match QuickBooks/Xero's expected format before import.
Which delimiter for European books?
Semicolon. EU-locale Excel and accounting tools treat the comma as a decimal separator, so a comma CSV merges into one column — semicolon keeps fields separate.
Should I use Download CSV or Excel-Ready CSV?
Excel-Ready CSV for accounting imports — it adds a UTF-8 BOM and CRLF so QuickBooks and Excel read encoding and rows correctly. Plain Download CSV (LF) is for code pipelines.
My transactions are wrapped in a `data` envelope — what do I do?
If scalar fields sit beside the array, extract $.data first with json-path-extractor so each transaction becomes a row instead of one wide row.
What about invoice line items?
Nested line-item arrays stay in one cell. If your import template needs one row per line, extract the line-items path and convert it separately.
Will extra fields on some transactions break the columns?
No. The union-of-keys header includes every field across all records, leaving empty cells where a transaction lacks one. The grid stays aligned.
Is my financial data uploaded?
No. Conversion runs entirely in your browser; sensitive records never reach a server.
How big a file can I convert?
Free: 2 MB / 500 rows. Pro: 100 MB / 100,000 rows. Split large ledgers by period if needed.
I'm starting from a Stripe export specifically — any tips?
Yes — the Stripe export guide covers extracting $.data, the smallest-unit amounts, and the Unix created timestamp, all of which apply before mapping to QuickBooks/Xero.
Can I reverse the conversion?
Yes — csv-to-json turns a CSV back into JSON, useful for re-feeding reconciled data into another system.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.