creatorvalet Search

Convert JSON to CSV

Nested objects become dot-notation columns. You decide what happens to the arrays — before anything is downloaded.

  • SECURE
  • NO UPLOADS
  • NO SIGNUP
  • BROWSER BASED
  • FREE
  • FOREVER.

Support us with a link or a share

Waiting
Size
Records
Rows
Columns
Arrays inside a record
№ 7501waiting

Nothing at the counter yet. Paste JSON, or drop a .json file on the JSON panel. The column names appear before anything is converted.

Nested keys
Null becomes
Delimiter

JSON to CSV is a flattening, not a translation

A CSV file is a grid: every row has the same columns, and every cell holds one value. JSON is a tree. Values contain objects, objects contain arrays, arrays contain more objects, and nothing forces two records to have the same shape. Converting the second into the first is not a translation — it is a flattening, and a flattening always makes decisions on your behalf.

Most converters make those decisions silently. You paste a document, a file appears, and the fact that a column was dropped or an array was collapsed into a string is something you discover two days later in a spreadsheet. This tool takes the opposite approach: it shows you the column names it is about to produce, tells you what it did to every nested object and every array, and lets you change the strategy before anything is downloaded.

Going the opposite way has its own page. CSV to JSON turns a grid back into records, and the decisions it has to make are about types rather than about shape — whether a cell of digits is a quantity or an identifier. Product GTINs belong in the second category, especially when they begin with zero; after the digits survive the export, the UPC generator can turn one into UPC-A bars. For an internal ID that contains letters or punctuation, use the barcode generator and choose Code 128 instead of forcing it into a retail format.

JSON and CSV, in brief

JSON
Full name JavaScript Object Notation
Extension .json
Format type Nested text data, six value kinds
MIME type application/json
CSV
Full name Comma-Separated Values
Extension .csv
Format type Plain text table, one record per line
MIME type text/csv

Nested objects become dotted column names

The uncontroversial part. An object inside an object becomes one column per leaf, with the path written out: {"user": {"address": {"city": "Austin"}}} becomes a column named user.address.city. The convention comes from pandas, jq and most data warehouses, so a file produced this way will look familiar to whoever receives it.

There is one caveat worth knowing before you load the result somewhere. Several SQL dialects — BigQuery in particular — reject or mangle a column name containing a dot, because the dot already means "field of a struct". If the CSV is headed for a database loader rather than a spreadsheet, switch the separator to an underscore and you get user_address_city instead. It is one click, and it saves an import error that is genuinely annoying to diagnose from the other end.

Arrays are the real problem, and they have three honest answers

An array inside a record has no single correct representation in a grid, which is exactly why converters differ so much. There are three reasonable answers, and which one is right depends entirely on what the array means.

Join it into one cell. ["red", "blue"] becomes red; blue. This is right for tags, categories, labels — anything where the list is a property of the record rather than a set of related records. It is compact and it keeps one row per record. The cost is that the values are now a string: splitting them apart again is only reliable if no value contains your separator, which is why the default here is a semicolon rather than a comma, and why the separator is a free text field rather than a fixed choice.

Number the columns. tags.0, tags.1, tags.2. This is right when the array has a fixed and small length and position carries meaning — coordinates, a fixed set of scores, the three most recent events. The widest record decides how many columns exist, so a document where one record has forty items and the rest have two produces thirty-eight mostly empty columns. The column preview makes that visible immediately.

One row per item. The record is repeated once for every element, with the surrounding fields duplicated on each row. This is denormalization, and it is what you want for order lines, comments, transactions — arrays whose elements are themselves records. It is also the only one of the three that lets a spreadsheet pivot or a database group over the array contents.

Denormalization has one sharp edge and the tool states it rather than hiding it: two arrays in the same record multiply. A record with three tags and four line items produces twelve rows, not seven, because there is no other mathematically consistent answer. When that is not what you meant, pick a single array to expand and let the others join into cells instead.

One more case is decided for you, because only one answer is defensible. An array that contains objects cannot be joined into a cell without destroying the objects, so it falls back to numbered columns — and says so on the receipt instead of writing [object Object] into your data, which is a genuinely common outcome elsewhere.

Uneven records, and the column union

Real JSON is ragged. An API omits null fields, a newer record has a field the older ones lack, an optional block appears in one entry out of five hundred. A converter that builds its header from the first record silently drops every field that appears later — the most damaging bug in this category, because the output looks perfectly fine.

Every key found anywhere in the document becomes a column here. Records that lack it get an empty cell, never the string undefined and never the word null unless you ask for it. The column preview shows a count such as 3/500 on any column that is not present in every row, so a rare field is something you notice before you build a report on it.

Types: what survives the trip

CSV has no type system, so every value ends up as text and the receiving program guesses. Three of those guesses are worth controlling.

null becomes an empty cell by default, which is what most spreadsheets and loaders expect. If your destination distinguishes "no value" from "empty string", you can write it out as null or NULL instead. Booleans keep the form JSON gave them — true and false, lowercase, not Excel's TRUE. Numbers are copied digit for digit from your source rather than being run through JavaScript, which matters more than it sounds: a nineteen-digit Snowflake or Twitter ID does not survive JSON.parse intact, and 12345678901234567890 comes back as 12345678901234567000 in every converter that takes the obvious route. Here the digits you pasted are the digits you get.

Delimiters, the byte order mark and Excel

The delimiter is not universal. Swedish, German, French and most other European Excel installations expect a semicolon, because the comma is the decimal separator in those locales. A comma-separated file opened there lands entirely in column A. If the file is for a colleague rather than a program, ask which one they need — the guide to the CSV format covers why the format has no real standard to appeal to. Need one value rather than a whole file? The CSV escape tool quotes a single field for a comma, semicolon or tab file, and reads a quoted field back.

The byte order mark is the other half of the same problem. It is three invisible bytes at the start of the file that tell Excel the text is UTF-8. Without it, Excel on Windows falls back to a legacy code page and Malmö arrives as Malmö. Adding it costs nothing for spreadsheets and can confuse a strict parser expecting the first character to be data, so it is a checkbox rather than a default you cannot see. It is written into the downloaded file only, never into what you copy. The difference between the two is exactly what CSV UTF-8 versus plain CSV means in Excel's own save dialog.

Nothing leaves this tab

The JSON people convert is usually an export: customer records, order history, a webhook payload, a user table dumped from an internal admin. All of it is parsed and flattened by JavaScript running in this page, and there is no upload endpoint to send it to. Open your browser's network panel and paste a document; the panel stays empty, because the flattening is a function call and not a round trip. If the output looks wrong before you convert, the JSON formatter points at the exact line, and the CSV viewer opens the result as a real table afterwards.

Have an idea for this tool?

Tell us what would make this tool more useful, or suggest another tool you would like us to build.

Questions

How do nested objects become CSV columns?

They are flattened with dot notation: {"user": {"address": {"city": "Austin"}}} becomes a column called user.address.city. Every level of nesting adds one segment, and the tool lists the column names before you convert anything so you can see exactly what you are about to get. If your target system dislikes dots in column names — BigQuery and most SQL loaders do — you can switch the separator to an underscore.

What happens to arrays inside my JSON?

You pick, because all three answers are correct in different situations. Joining puts every item in one cell separated by a semicolon, which suits tags and categories. Numbered columns give you tags.0, tags.1 and so on, which suits fixed-length data. One row per item duplicates the surrounding fields onto a row for each element, which is what you want for order lines or comments. Arrays that contain objects cannot be joined into a cell without destroying them, so those fall back to numbered columns and the tool tells you it did.

Why do some of my records have fewer fields than others?

That is normal in JSON and it is the hardest part of writing a correct CSV. Every key found anywhere in the document becomes a column — the union, not the first record — and records that lack that key get an empty cell rather than the word undefined. The column preview marks how many records actually contain each column, so a field present in 3 of 500 records is visible before you open the file in a spreadsheet.

What if a key already contains the separator?

Both fields are kept, and the tool says so. {"a.b": 1, "a": {"b": 2}} is two different fields that both want to be called a.b, so the second one becomes a.b_2 rather than quietly overwriting the first. Switching the separator to an underscore usually removes the clash entirely, and a key that is the empty string is named after its position — column_1 — because an unnamed field is still a field with values in it.