JSON is how apps and APIs hand over data: product feeds, order exports, form submissions, analytics reports. Spreadsheets want rows and columns. The gap between the two is nesting. A product has variants, each variant has a price and a SKU, and a plain converter either drops those fields or dumps them into one unreadable cell.
This converter flattens nested objects into named columns, gives you four ways to handle arrays, previews the result, and downloads a CSV that opens cleanly in Excel or Google Sheets. It also converts CSV back to JSON. Everything runs in your browser, so API responses with customer data never leave your device.
How to convert JSON to CSV
- Paste JSON into the box, click Open .json file, or try Sample: Shopify products.
- Check the status line. It says whether the JSON is valid and how many rows it found. If it is not valid, it shows the line and column of the first problem.
- Under Rows come from, confirm which array holds your records. The converter picks the largest array of objects automatically, such as
productsordata.items, and lists the others so you can switch. - Choose how arrays inside a row are handled and pick a delimiter.
- Look at the preview of the first 100 rows, then click Download CSV or Copy CSV.
JSON Lines files (one JSON object per line, also called NDJSON, common in log and data exports) are detected automatically. Format JSON pretty-prints what you pasted so it is easier to read.
How nested objects become columns
With Flatten nested objects on, each nested field gets a column named by its path, joined with dots. This record:
{"title": "Linen Throw Blanket", "seo": {"title": "Stonewashed Linen Throw", "description": "Soft European flax linen throw."}}
becomes three columns: title, seo.title and seo.description. Paths can go as deep as the data does, so shipping.address.city works the same way. Columns appear in the order fields are first seen, and a record that lacks a field gets an empty cell. Turn flattening off and nested objects are written as JSON text in a single cell instead.
Records do not need the same fields. API data is often uneven: one order has a discount code, the next does not, a third has a gift note. The converter collects every field from every record, so the CSV has one column for each field that appears anywhere, and the stat boxes show how many columns came from nested paths. If a key already contains a dot, such as "size.us", the column name will look like a path; that only matters if you later convert the CSV back to JSON with nesting turned on, where it would become a nested object. In that case, untick Rebuild nested objects on the CSV to JSON tab.
Four ways to handle arrays
The sample is a Shopify-style products file with two products. Each has tags, an options array and a variants array of objects. Here is what each array setting produces:
| Setting | Result for the Linen Throw | Rows and columns |
|---|---|---|
| Join with | | tags = linen|bedroom|gift, variants.sku = HL-THR-OAT|HL-THR-SAG, variants.price = 89.00|89.00 | 2 rows, 18 columns |
| Numbered columns | tags.0 = linen, tags.1 = bedroom, variants.0.sku = HL-THR-OAT, variants.1.sku = HL-THR-SAG | 2 rows, one column per item position |
| JSON text | tags = ["linen","bedroom","gift"], variants = the full array as JSON | 2 rows, few columns |
| One row per item (variants) | Two rows for the throw, one per variant, each with the product title and the variant's sku, price and availability | 4 rows (2 products × 2 variants) |
Join keeps one row per record and works best for short lists like tags. For arrays of objects it joins each field separately, so variants.sku and variants.price line up by position: the second SKU goes with the second price. An empty value keeps its slot, which is why the throw's compare-at prices read 110.00| when only the first variant has one.
One row per item is what most people want for orders with line items or products with variants. Pick the array to expand, and every other field of the record is repeated on each row. Other arrays in the same record are joined. A record whose array is empty still gets one row, so nothing disappears.
Numbered columns suits arrays with a fixed size, such as up to three images. With long, uneven arrays it creates many mostly empty columns.
Worked example: orders with line items
Order exports are the most common reason people need this tool. Take two orders in this shape (shortened):
{"orders": [{"name": "#1041", "email": "dana@example.com", "total": "131.00", "line_items": [{"sku": "HL-THR-OAT", "qty": 1, "price": "89.00"}, {"sku": "HL-TRY-S", "qty": 1, "price": "42.00"}]}, {"name": "#1042", "email": "li@example.com", "total": "18.00", "line_items": [{"sku": "HL-MUG-12", "qty": 1, "price": "18.00"}]}]}
Set arrays to One row per item and choose line_items. The CSV comes out as:
| name | total | line_items.sku | line_items.qty | line_items.price | |
|---|---|---|---|---|---|
| #1041 | dana@example.com | 131.00 | HL-THR-OAT | 1 | 89.00 |
| #1041 | dana@example.com | 131.00 | HL-TRY-S | 1 | 42.00 |
| #1042 | li@example.com | 18.00 | HL-MUG-12 | 1 | 18.00 |
Now a pivot table can sum quantity by SKU. Remember that order-level fields repeat on every line, so do not sum the total column in this layout; use the join setting instead when you need one row per order for revenue totals.
Where JSON usually comes from
- Store and app exports. Many apps offer a JSON download next to CSV, and webhook logs in tools like Zapier or Make show each payload as JSON you can copy.
- APIs. Responses from REST APIs such as WooCommerce, Stripe or your email platform usually wrap the records in a key like data, items or results. The converter finds that array for you, and a record count in the dropdown confirms you picked the right one.
- Your own Shopify store. Public Shopify storefronts answer at /products.json with a product list, which is useful for a quick catalog snapshot of your own store in a spreadsheet.
- Browser developer tools. In the Network tab, a request's response can be copied as JSON and pasted here.
Only convert data you are allowed to use. Customer data from APIs is still personal data once it is in a spreadsheet, so keep the CSV in the same place you would keep the original export.
Delimiter, header and Excel
Comma is the default. Choose semicolon if your Excel uses a comma as the decimal separator, as in much of Europe and Latin America, tab for a TSV file, or pipe for systems that ask for it. The header row can be switched off. UTF-8 BOM is on by default: it adds an invisible marker at the start of the file so Excel shows accented letters, currency symbols and emoji correctly when you double-click the CSV. Google Sheets, Shopify and most other tools ignore it. Untick it only if a system specifically rejects it.
Values are written exactly as they appear in the JSON. Numbers are not reformatted, true and false stay as words, and null becomes an empty cell. Fields that contain the delimiter, quotes or line breaks are quoted the standard way, so a title like Oak Serving Tray, Small stays in one cell. For a native Excel file with a bold, frozen header, convert the CSV with the CSV to Excel converter.
CSV to JSON
Open the CSV to JSON tab, paste CSV or open a file, and the JSON appears as you type. The delimiter is detected, the first row is used as keys, and empty or repeated header names get unique names such as column_3 or price_2.
- Types: numbers become JSON numbers, true and false become booleans and null becomes null. Values with leading zeros such as ZIP code 02134 stay text, so they are not damaged, and so do numbers longer than 15 digits.
- Nested objects: headers with dots are rebuilt into objects, so seo.title and seo.description become one seo object. Numbered headers like tags.0 and tags.1 become an array.
- Output shapes: an array of objects, an array of arrays (header first), or JSON Lines.
- Indent: 2 spaces, 4 spaces or minified.
The sample turns HL-THR-OAT,Linen Throw Blanket,89.00,14,02134,true into an object with price 89, stock 14, zip "02134" and active true, plus a nested seo object. A value such as 1,5 in a semicolon file stays the text "1,5", because the converter does not guess at decimal commas.
Errors and how to fix them
| Message | Usual cause |
|---|---|
| Extra comma before ] or } | A trailing comma after the last item, which JavaScript allows but JSON does not. |
| Keys need double quotes | The text is a JavaScript object or Python dictionary, not JSON. Replace single quotes with double quotes. |
| Expected a key in double quotes | An unquoted key such as {sku: "A1"}. |
| The JSON ends too early | The paste was cut off, or a bracket was never closed. |
| Extra text after the end of the JSON | Two JSON documents pasted together, or log text around the JSON. |
Each message comes with the line and column, so in a long file you can jump straight to the problem.
Other ways to do it, and when they fit better
| Method | Good for | Trade-off |
|---|---|---|
| This converter | One-off and weekly conversions, nested data, private data | Manual: you paste or open the file each time |
| Excel Power Query (Data > Get Data > From File > From JSON) | A report you refresh from the same file every week | Each nested level has to be expanded by hand in the query editor |
| Google Sheets with Apps Script | Pulling an API into a sheet on a schedule | You write and maintain the script |
| Python (pandas json_normalize) or jq | Very large files and automated pipelines | Needs a developer setup |
For most store owners and marketers the answer is simple: if it is a file you get now and then, convert it here; if it is a feed you need every morning, it belongs in a scheduled job or a tool that connects to the source.
Limits to know
- Files of tens of megabytes work; the preview shows the first 100 rows and the CSV contains all of them. Very large files depend on your device's memory.
- JSON numbers with more than 15 or 16 significant digits, such as 19-digit IDs from some APIs, lose precision when any browser reads them. If your IDs are that long, ask the API for them as strings.
- Arrays nested inside arrays (for example option values inside an options array) are kept as JSON text in their cell when joined.
- Converting a store's products JSON gives you a CSV of that data, not a file in Shopify's product import format, which uses its own column names.
If what you really want is to copy products from a public Shopify or WooCommerce store into your own, with variants, images and prices mapped correctly, the AM Jarvis Product Importer does that directly, and our guide to Shopify CSV imports explains the native format if you prefer to build the file yourself.