Quick answer: Use CSV when your data is a flat table that humans will open in a spreadsheet or load into an analytics tool. Use JSON when the data is nested, needs real types (numbers, booleans, null), or is exchanged between programs through an API. For logs and streaming records, use JSON Lines, which gives you JSON's types with CSV's one-record-per-line shape.
A product manager asks for "an export of all orders." You could produce a CSV in ten minutes with one row per order. Then you remember each order has several line items, a shipping address, and a list of applied discounts. Suddenly one row per order does not fit, and you are choosing between twenty columns named item_1_sku, item_2_sku, or switching to JSON. This decision comes up constantly, and it is easier when you know exactly where each format breaks.
Compare a small sample using the JSON to CSV Converter and the CSV to JSON Converter to see how the same records map between the two formats.
JSON vs CSV at a Glance
| JSON | CSV | |
|---|---|---|
| Structure | Nested objects and arrays | Flat rows and columns |
| Data types | string, number, boolean, null, object, array | None; everything is text |
| Schema | Optional (JSON Schema) | Header row only, if present |
| Standard | RFC 8259 (strict) | RFC 4180 (loosely followed) |
| Size for tabular data | Larger (keys repeated per row) | Smaller (keys once in header) |
| Human editing | Any text editor | Excel, Sheets, any text editor |
| Streaming | Hard (needs JSON Lines) | Natural (one row per line) |
| Nulls vs empty | Explicit null | Ambiguous: empty cell |
| Unicode handling | UTF-8 by spec | Encoding varies; Excel often needs a BOM |
| Typical use | APIs, config, documents | Exports, spreadsheets, bulk loads |
Structure: Nested vs Flat
This is the difference that matters most. CSV is a grid. Every record has the same columns, and every cell holds one value. JSON is a tree. A value can be an object, which can contain arrays, which can contain more objects. The same order looks like this in each:
{
"orderId": 1042,
"customer": { "name": "Priya", "email": "priya@example.com" },
"items": [
{ "sku": "A-100", "qty": 2, "price": 19.99 },
{ "sku": "B-220", "qty": 1, "price": 5.00 }
],
"paid": true
}
orderId,customer.name,customer.email,sku,qty,price,paid
1042,Priya,priya@example.com,A-100,2,19.99,true
1042,Priya,priya@example.com,B-220,1,5.00,true
To fit the order into CSV you had to pick a strategy: here, one row per line item with the order fields repeated. The other options are one row per order with the items stuffed into a JSON string in a cell, or a second file for items joined by orderId. None of these is wrong, but every one is a decision the JSON version never had to make. The JSON to CSV guide walks through each flattening strategy with code.
If your data is genuinely flat, a list of sensor readings, a mailing list, a price table, CSV loses nothing and the nesting advantage of JSON is irrelevant.
Data Types: JSON Has Them, CSV Does Not
JSON distinguishes 42, "42", true, and null. CSV has one type: text. The program reading the file guesses, and the guesses are where data gets silently damaged:
- A zip code
02134becomes the number2134. - A product code
1E5becomes100000. - A 19-digit order ID is rounded by Excel to 15 significant digits.
- The customer surname
Nullbecomes an actual null in pandas. - A date
03/04/2026is March 4 in one locale and April 3 in another.
These problems are not hypothetical; they are the standard list of bugs in the CSV to JSON conversion guide. With JSON, a number is a number because the producer wrote it without quotes, and a string stays a string. JSON still has its own number limits, covered in JSON number precision, but at least the type itself survives the trip.
File Size: CSV Wins for Tables
JSON repeats every key in every record. For a table with 20 columns and a million rows, that is 20 million key strings that CSV writes once. In practice a JSON array of flat objects is substantially larger than the equivalent CSV, and the gap grows as keys get longer relative to the values. Minifying JSON removes the whitespace but not the keys, so the gap remains; see how to minify JSON for what minification actually saves.
Two caveats. First, gzip changes the picture: repeated keys compress extremely well, so compressed JSON and compressed CSV land much closer together. Second, size only matters at scale. For a 200-row export nobody will notice the difference, so pick on structure, not bytes.
Tooling: Excel vs Code
Double-click a CSV and it opens in Excel, Numbers, or Google Sheets with columns already laid out. Business users can sort, filter, and pivot without asking anyone. That is CSV's killer feature and the reason it will never go away.
Double-click a JSON file and you get a text editor, or a browser tab showing a wall of text. Reading it comfortably takes a formatter (JSON Prettifier works for files up to 5 MB), and doing anything with it takes code. Excel can import JSON through Power Query, but it is a multi-step wizard, not a double-click. The how to open a JSON file guide covers the options.
On the programming side it flips. Every language parses JSON in one call with correct types. Parsing CSV correctly, with quoted fields, embedded commas, embedded newlines, and escaped quotes, needs a real library, and the "simple" line.split(",") approach breaks on the first address with a comma in it.
Streaming and Appending
CSV is naturally streamable: each line is a record, so you can process a 10 GB file with constant memory, and appending a record means appending a line. A JSON array is not: the opening [ and closing ] wrap everything, so a standard parser needs the whole document, and you cannot append without rewriting the last byte.
The fix is JSON Lines: one JSON object per line, no outer array. It streams and appends exactly like CSV while keeping nesting and types. It is the default output format for structured loggers and the input format for bulk APIs at Elasticsearch, BigQuery, and most LLM fine-tuning pipelines.
{"ts":"2026-08-28T09:14:02Z","level":"info","msg":"order placed","orderId":1042}
{"ts":"2026-08-28T09:14:05Z","level":"warn","msg":"payment retry","orderId":1042,"attempt":2}
Schema and Validation
A CSV header tells you column names and nothing else. There is no standard way to say "qty must be a positive integer" or "email is required." JSON has JSON Schema, which lets you publish the contract, validate payloads automatically, and generate types for TypeScript, Python, or Java. For data crossing a team or company boundary, that contract is worth more than any size difference.
CSV's own spec, RFC 4180, is short and widely ignored. Delimiters vary by locale (semicolons in much of Europe because the comma is the decimal separator), quoting rules vary by tool, and line endings vary by OS. JSON's spec, RFC 8259, is strict, and a document either parses or it does not.
Decision Rules by Use Case
| Use case | Pick | Why |
|---|---|---|
| Analytics export for a spreadsheet user | CSV | Opens directly in Excel; data is tabular |
| Bulk load into a SQL database | CSV | COPY / LOAD DATA accept it natively and fast |
| REST or GraphQL API | JSON | Nested, typed, parsed in one call everywhere |
| Application logs | JSON Lines | Appendable, streamable, keeps structure |
| Config files | JSON (or YAML) | Nested settings, booleans, nulls |
| Data science dataset, flat | CSV (or Parquet) | pandas reads it in one line; smaller |
| Data science dataset, nested | JSON Lines | pandas read_json with lines=True |
| Interchange with a non-technical partner | CSV | They can open and inspect it |
| Interchange between two systems | JSON | Schema, types, no delimiter ambiguity |
Common Mistakes
- Choosing CSV for nested data to "keep it simple." You end up with columns like
item_7_priceor JSON strings inside cells, which is the complexity you were avoiding plus a worse format. - Choosing JSON for a spreadsheet audience. If the recipient's first move is to open it in Excel, give them CSV. They will otherwise ask you to convert it anyway.
- Writing CSV by string concatenation. A single value containing a comma, a quote, or a newline corrupts the row. Use the CSV library in your language; every one has one.
- Forgetting the UTF-8 BOM for Excel. Excel on Windows often shows non-ASCII characters as garbage in a CSV without a BOM, yet a BOM in a JSON file is an error. The encoding and BOM guide explains both sides.
- Using a JSON array where you needed JSON Lines. If the file will grow over time or be processed record by record, the outer array will eventually be the thing that breaks.
How JSON vs CSV Fits With XML and YAML
CSV is the only one of the four that cannot nest. XML can and is heavier than JSON; YAML can and is easier for humans to write but easier to get subtly wrong. If the real choice is between the structured formats, the JSON vs XML and JSON vs YAML comparisons cover those trade-offs. If the question is "grid or tree," it is this article, and the answer is almost always visible in the data itself.