JSON to CSV Converter

Convert JSON to CSV in your browser: nested keys, delimiters, a BOM for Excel and formula protection.

Or drag and drop a file onto this box. Files up to 100 MB.
Options

Formula protection puts a single quote before text that starts with = + - @, so a spreadsheet will not run it as a formula.

Nested objects become dotted column names, a row that lacks a key gets an empty cell, and a number with more than 15 significant digits is copied exactly as written.

CSV output

    
                    

    A JSON to CSV converter turns JSON data into rows and columns that a spreadsheet, a database import or a reporting tool can open. This page takes an array of objects, a single object, an array of arrays or a plain list of values, flattens nested objects into dotted column names, and writes comma, semicolon, tab or pipe separated text. You choose how arrays are written, whether there is a header row, how fields are quoted, which line ending to use, and whether to add a byte order mark so Excel reads accented characters correctly. Large files are converted in a background worker, so the page stays responsive while tens of thousands of rows are processed.

    How do I convert JSON to CSV?

    Paste your JSON into the box, choose a .json file, or load the sample. The table preview and the raw CSV appear on the right as soon as the JSON is valid. Change an option to update the result, then copy the CSV or download it as a .csv file.

    How to use this JSON to CSV converter

    • Provide the JSON: paste it, drag a file onto the upload box, or send it from the JSON Formatter. An invalid document shows the line and column of the problem.
    • Pick the delimiter: comma is the default. Semicolon suits Excel in many European locales, and tab or pipe help when your values contain commas.
    • Decide how arrays are written: join the values into one cell, expand them into indexed columns, or keep them as a JSON string.
    • Set the file details: header row, quote every field, LF or CRLF line endings, and the UTF-8 byte order mark.
    • Copy or download: the table preview shows the first 100 rows, while Copy and Download use every row.

    To go the other way, the CSV to JSON converter reads the kind of file this page writes. If you want typed cells, several sheets, or a file Excel opens without an import step, use the JSON to Excel converter instead.

    How are nested objects, arrays, null and missing keys converted?

    Every item in the array becomes one line. Nested objects are flattened with dot notation, so {"address": {"city": "London"}} becomes a column named address.city. The columns are the union of every key in every row, in the order they first appear, and a row that lacks a key gets an empty cell.

    How each kind of JSON value is written
    In the JSONIn the CSV
    A nested object, such as {"a": {"b": 1}}A column named a.b holding 1
    An array of plain values, with the Join option (the default)One cell, the values separated by "; " (you can pick another separator), for example math; poetry
    An array of plain values, with Indexed columnsOne column per position: tags.0, tags.1, and so on
    An array that holds objects or other arrays, with the Join optionThe array kept as compact JSON text in one cell, with a notice. Indexed columns flatten it instead, as in lines.0.sku
    Any array, with Keep as a JSON stringThe compact JSON text of the array, in quotes
    An empty array or an empty objectAn empty cell for an empty array with Join, otherwise []; an empty object is written as {}
    null or a key that is missing from a rowAn empty cell. The two look the same in a CSV file
    true and falseThe text true and false
    A numberThe number as JavaScript writes it, such as 24.5 or -3. A number with more than 15 significant digits is copied exactly as it appears in your JSON, and a warning says so
    Text with the delimiter, a double quote or a line breakWrapped in double quotes, with each inner quote doubled, as RFC 4180 describes

    Two different keys can flatten to the same column name, for example a key that is literally called a.b and a nested object a with a key b. When that happens the later value wins and a warning counts the values that were overwritten.

    Worked example: nested objects, arrays, null and a value with a comma

    This input has rows with different keys, a nested object, an empty array, a null, and a text value that holds a comma and a line break. The CSV below is the exact output of this page with the default options, and a test re-checks it.

    JSON input

    [
      {
        "id": 1,
        "name": "Ada Lovelace",
        "address": {
          "city": "London",
          "zip": "02134"
        },
        "tags": [
          "math",
          "poetry"
        ]
      },
      {
        "id": 2,
        "name": "Grace Hopper",
        "address": {
          "city": "New York"
        },
        "tags": [],
        "note": null
      },
      {
        "id": 3,
        "name": "Zoë Müller",
        "tags": [
          "go"
        ],
        "note": "Line one\nLine two, with a comma"
      }
    ]

    CSV output

    id,name,address.city,address.zip,tags,note
    1,Ada Lovelace,London,02134,math; poetry,
    2,Grace Hopper,New York,,,
    3,Zoë Müller,,,go,"Line one
    Line two, with a comma"

    The address.city and address.zip columns come from the nested object, and the second row has a city but no zip, so that cell is empty. The third row has no address at all, and the second row has an empty tags array, so both give empty cells. The note column exists because two rows have it, and a null and a missing key look the same. The text in the last cell contains a comma and a line break, so it is wrapped in double quotes and stays one cell. The zip 02134 keeps its leading zero because it is text in the JSON.

    Three more worked examples

    1. One object with an array, written three ways

    A single object becomes one row. The array of items is the only part that depends on your choice. Here is the input, then the output for each option.

    JSON input

    {
      "order": "A-1001",
      "items": [
        "pen",
        "ink",
        "pad"
      ],
      "ship": {
        "to": "Oslo",
        "express": true
      }
    }

    Output with Join the values into one cell (the default)

    order,items,ship.to,ship.express
    A-1001,pen; ink; pad,Oslo,true

    Output with Indexed columns

    order,items.0,items.1,items.2,ship.to,ship.express
    A-1001,pen,ink,pad,Oslo,true

    Output with Keep as a JSON string

    order,items,ship.to,ship.express
    A-1001,"[""pen"",""ink"",""pad""]",Oslo,true

    2. An array of objects inside a row

    Order lines are objects, so joining them is not possible and the Join option keeps the array as JSON text. Indexed columns flatten each line into its own columns, which is usually what a spreadsheet user wants when every row has only a few lines.

    JSON input

    {"id":7,"lines":[{"sku":"K1","qty":2},{"sku":"K2","qty":1}]}

    Output with Join

    id,lines
    7,"[{""sku"":""K1"",""qty"":2},{""sku"":""K2"",""qty"":1}]"

    Output with Indexed columns

    id,lines.0.sku,lines.0.qty,lines.1.sku,lines.1.qty
    7,K1,2,K2,1

    3. An array of arrays, a single object and a plain list

    An array of arrays is written row by row exactly as given. With the header row off the output is just the rows, and with it on the columns are named column_1, column_2 and so on, so switch the header off when your first inner array already holds the column names.

    JSON input, an array of arrays

    [["name","score"],["Ada",91],["Grace",88.5]]

    CSV output with the header row off

    name,score
    Ada,91
    Grace,88.5

    A list of plain values gets one column named value, and a null in it is written as "" because a lone empty value would otherwise be a blank line that CSV readers skip. A single object is one row, with its keys as the header.

    JSON input, a list of plain values

    ["red","green",null,"blue"]

    CSV output

    value
    red
    green
    ""
    blue

    Which delimiter should I use?

    Comma is the standard and what most programs expect. In locales where the comma is the decimal separator, which includes much of Europe and Latin America, Excel expects a semicolon, and a comma separated file opens with everything squeezed into the first column. Tab gives a TSV file, which is handy when the values contain commas, and a pipe works well when they contain commas and tabs. Whatever you choose, a value that contains the delimiter is quoted. Here is one row written with each of the three common delimiters, where the price 3,50 holds a comma.

    JSON input

    [{"city":"Zürich","price":"3,50","note":"say \"hi\""}]

    Comma

    city,price,note
    Zürich,"3,50","say ""hi"""

    Semicolon

    city;price;note
    Zürich;3,50;"say ""hi"""

    Tab

    city	price	note
    Zürich	3,50	"say ""hi"""

    Common problems and how to fix them

    Excel shows garbled characters instead of accented letters

    When you double-click a CSV, Excel guesses its encoding, and a file without a byte order mark is often read with the local ANSI code page. A name such as Zoë then appears as Zoë. Tick Add UTF-8 BOM before you download: the three bytes EF BB BF at the start of the file tell Excel to read UTF-8. Leave the option off for programs that read the file directly, because some of them treat the mark as part of the first header name.

    Leading zeros disappear

    The CSV written here keeps 02134 exactly as the JSON text has it. Excel, however, turns a column that looks numeric into numbers when it opens the file, which drops the zero. Open the file through Data, From Text/CSV, and set that column to Text. The JSON to Excel converter writes text cells directly, so the zeros survive without any import step.

    Long numbers end in zeros

    Spreadsheets keep 15 significant digits of a number. A JSON number with more digits is copied into the CSV unchanged and flagged with a warning, but Excel will round it when it reads the column as a number, so import long IDs as Text. In this example the 20-digit id is written exactly:

    JSON input

    [{"id":12345678901234567890,"zip":"02134","qty":42}]

    CSV output

    id,zip,qty
    12345678901234567890,02134,42

    Formula injection

    A spreadsheet can treat a cell that begins with =, +, - or @ as a formula, which attackers abuse when data they control ends up in an export. With Protect against formula injection on, which is the default, text that starts with one of those characters, or with a tab or carriage return, gets a leading single quote so it stays text. JSON numbers such as -5 are real numbers and are left alone.

    JSON input

    [{"note":"=1+1","phone":"+1 555 0100","delta":-5,"mail":"@home"}]

    CSV output with protection on (the default)

    note,phone,delta,mail
    '=1+1,'+1 555 0100,-5,'@home

    CSV output with protection off

    note,phone,delta,mail
    =1+1,+1 555 0100,-5,@home

    The trade-off is that a phone number written as text, such as +1 555 0100, also gets the quote. Turn the option off when the CSV goes to a program rather than to a person with a spreadsheet.

    Dates are plain text

    JSON has no date type, so a date is a string and is written as it is. Excel may reinterpret it according to your locale when it opens the file, so check the column after you open it.

    Line endings

    LF is the default and works in Excel, LibreOffice and every command line tool. Choose CRLF if a strict RFC 4180 reader or an older Windows program needs it.

    CSV or Excel: which one should I export?

    Choose CSV when the data is going into a database import, a script, a version control diff or any tool that reads text. It is small, universal and easy to inspect, but it carries no types, so every reader has to guess what a column holds. Choose Excel when a person will open the result: numbers stay numbers, text such as 007 stays text, one JSON object can become several sheets, and there is no import step. The JSON to Excel converter shares the same flattening rules as this page, so you can switch between them without changing how your data maps.

    What are the limits of this converter?

    Files up to 100 MB are accepted. A file above about 1.5 MB is converted straight from the file and is not placed in the text box. The conversion runs in a background worker with a time limit that grows with the file size, a progress count, and a Cancel button. The table preview shows the first 100 rows and up to 60 columns, and the raw text preview shows the first 200,000 characters, while Download always writes the full result. Copy stops above about 5 million characters, so use Download for very large output. The output is limited to 16,384 columns.

    Related tools

    Frequently Asked Questions

    How do I convert JSON to CSV?

    Paste your JSON, choose a .json file or load the sample. The table preview and the raw CSV appear as soon as the JSON is valid. Pick a delimiter and the other options, then copy the CSV or download it as a .csv file.

    How are nested objects and arrays turned into columns?

    A nested object is flattened with dot notation, so address.city becomes a column named address.city. An array can be joined into one cell, expanded into indexed columns such as tags.0 and tags.1, or kept as a JSON string. Rows with different keys get empty cells for the keys they lack.

    Why does Excel show garbled characters in my CSV?

    Excel often reads a CSV that has no byte order mark with the local ANSI code page, so accented letters turn into pairs such as ö. Tick Add UTF-8 BOM before you download and Excel reads the file as UTF-8.

    Is my JSON uploaded anywhere?

    No. The JSON is converted by a script running in your browser tab, and the converter does not send it anywhere. The page uses Google Analytics for anonymous usage counts, which never include your JSON, keys or file names.

    What does protect against formula injection do?

    A spreadsheet can run a cell that starts with = + - or @ as a formula. With this option on, which is the default, text that starts with one of those characters, or with a tab or carriage return, gets a leading single quote so it stays text. JSON numbers such as -5 are not changed.

    Can it convert a large JSON file?

    Yes. Files up to 100 MB are accepted and converted in a background worker, so the page stays responsive while a progress count runs, and a Cancel button appears if it takes longer than a second. In our test, 100,000 rows convert without freezing the page.

    Built and maintained by Deepak Kumar.