Geonode logo
Geonode Team

Geonode Team

Updated: September 2, 2026

Published: 2026-09-02

JSON vs CSV: Which Format Should You Use?

The usual comparison says JSON is structured and CSV is simple. That is true and it misses the difference that causes real problems. JSON is a specification with mandatory rules. CSV is a description of what most implementations happen to do, written down after the fact. That asymmetry explains nearly every CSV problem you have ever had, and it should shape which format you pick.

Why we are writing this: we are Geonode and we sell proxies to people who collect data, so we watch a lot of scraped datasets get written to disk in the wrong format. The disclaimer is easy — format choice has nothing to do with proxies and we make no money from your decision here. What it does affect is your storage bill, your processing time, and how much of your week you spend debugging why a field containing a comma broke a downstream import. Those are real costs and they are entirely within your control before you write the first record.

The Fundamental Difference: One Is a Standard, the Other Is a Habit

This is the thing to understand first, because everything else follows from it.

JSON is standardised. RFC 8259 is an Internet Standards Track document. It has a formal grammar, mandatory requirements, and it explicitly exists to remove "inconsistencies with other specifications of JSON" and repair "specification errors". If two JSON parsers disagree, at least one of them is wrong and the specification says which.

CSV is not. RFC 4180 is Informational, and it says so about itself in the plainest terms:

While there are various specifications and implementations for the CSV format... there is no formal specification in existence, which allows for a wide variety of interpretations of CSV files. This section documents the format that seems to be followed by most implementations.

"Seems to be followed by most implementations" is doing a great deal of work in that sentence. RFC 4180 is a description of common practice, not a definition. If two CSV parsers disagree, both may be right.

This is why CSV problems have the character they do. They are not bugs so much as legitimate disagreements about a format nobody ever fully defined — which is also why they surface at integration boundaries, months after the file was written, in somebody else's tooling.

What CSV Actually Guarantees

RFC 4180 documents the common conventions, and it is worth knowing what they are because the deviations are where the trouble lives.

Records are separated by CRLF. The last record may or may not have a trailing line break. There may be an optional header line. Fields are separated by commas, each line should have the same number of fields, and "Spaces are considered part of a field and should not be ignored."

Quoting is where it gets interesting:

Each field may or may not be enclosed in double quotes (however some programs, such as Microsoft Excel, do not use double quotes at all).

And fields "containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes", with an embedded double quote escaped "by preceding it with another double quote".

Note the modal verbs. "May or may not." "Should." The RFC is describing tendencies. And the parenthetical about Excel is the document conceding, in 2005, that the most widely used CSV tool in the world does not follow the convention.

The practical consequences, in the order they will bite you:

Delimiters vary by locale. Countries using a comma as the decimal separator commonly use a semicolon as the field delimiter. A file exported by a colleague in Germany may not parse with a comma-based reader, and neither of you has done anything wrong.

Encoding is undeclared. Nothing in a CSV file states its character encoding. UTF-8, Latin-1, Windows-1252 and UTF-16 all produce a file that looks like CSV and reads as mojibake in the wrong parser. Byte order marks appear inconsistently and break naive header parsing.

Line endings vary. CRLF, LF, and — in fields containing embedded newlines — either, inside quotes.

Types do not exist. Everything is text. 007 becomes 7, 2026-09-02 becomes a date in one tool and a string in another, and a leading + disappears. Round-tripping a CSV through a spreadsheet is genuinely lossy.

And CSV files can execute code. A field beginning with =, +, - or @ may be interpreted as a formula by spreadsheet software. This is formula injection, it is a real vulnerability when you write user-supplied data into a CSV that someone will open in Excel, and the mitigation is to prefix such fields with a single quote or otherwise neutralise them before writing. If your pipeline produces CSVs from scraped or user-submitted content, this is worth handling deliberately.

What JSON Guarantees and Where It Still Bites

JSON's specification is stricter, and the guarantees are correspondingly stronger.

Encoding is settled. RFC 8259 §8.1: "JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8." It also states that implementations "MUST NOT add a byte order mark" to networked JSON text, while permitting parsers to ignore one. The entire class of encoding-guessing problems that plagues CSV simply does not exist here.

Types exist. Strings, numbers, booleans, null, objects and arrays are distinguishable in the grammar. "007" and 7 are different values and stay different.

Nesting is native. Hierarchical data has an obvious representation rather than requiring a convention nobody agreed on.

Two places where JSON is less absolute than people assume:

Duplicate keys are only discouraged. The spec says "The names within an object SHOULD be unique" — SHOULD, not MUST. And it is candid about the consequence: when names are not unique, "the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse."

Number precision is guidance, not a rule. The spec allows implementations to set limits on range and precision, and observes that good interoperability comes from expecting no more than IEEE 754 binary64 provides. It names the failure case directly: "A JSON number such as 1E400 or 3.141592653589793238462643383279 may indicate potential interoperability problems."

In practice this is the silent bug that ships. Large 64-bit identifiers lose precision when parsed into JavaScript numbers, nothing throws, and two distinct records can become the same value. The standard mitigation is to serialise large integers as strings — which is worth doing at the point where you write the data rather than discovering it downstream. We went into the parser side of this in our guide to JSON.parse.

Size and Speed

The trade-off is real, and the direction is not always what people expect.

CSV is smaller for flat tabular data, typically by a wide margin, because field names appear once in the header rather than in every record. A million rows of five fields stores five field names in CSV and five million in JSON.

Compression narrows the gap dramatically. Repeated keys compress extremely well. After gzip, the JSON penalty on uniform records often falls to something modest — occasionally to nothing. If you are storing compressed data, and you should be, the size argument for CSV is much weaker than the raw numbers suggest.

CSV parses faster for simple cases and slower for correct ones. A naive split(',') is very fast and wrong. A conforming parser that handles quoting, embedded newlines and escaped quotes correctly is closer to JSON parsing in cost. Most CSV speed comparisons are quietly comparing a wrong parser against a right one.

JSON's real cost is memory, not CPU. A single large JSON document must generally be held in memory to parse. A CSV can be processed row by row from a stream in constant memory. For a ten-gigabyte file, that difference is not a performance detail; it is the difference between possible and impossible on a given machine.

Which is exactly the problem the next section solves.

The Middle Ground: JSON Lines

JSON Lines — also called NDJSON or newline-delimited JSON — is one JSON document per line, with no wrapping array. It is the format most people should be using and comparatively few know about.

{"id": 1, "name": "Ada", "tags": ["engineer"]}
{"id": 2, "name": "Grace", "tags": ["engineer", "admiral"]}

What it gives you:

Streaming. Each line parses independently, so you process a hundred-gigabyte file in constant memory. This removes JSON's single biggest practical disadvantage.

Append-only writes. New records append to the end. No wrapping array to close, which means no rewriting the file and no corrupt output if a process dies mid-write.

Partial recovery. A truncated file still yields every complete line. A truncated JSON array yields nothing at all — one missing bracket and the whole document is unparseable. For anything written by a long-running job, this alone justifies the choice.

Trivial parallelism. Split by line and process shards independently. No cross-line state.

Full JSON semantics. Types, nesting and unambiguous encoding, all retained.

The costs are honest and small: slightly larger than CSV, not directly openable in a spreadsheet, and each record carries its keys. For scraped data, log output, event streams and anything appended incrementally, it is the right default — and it is what we would suggest to anyone writing collection output to disk.

Beyond Both: Parquet and Friends

Worth knowing about, because for analytical workloads the JSON-versus-CSV question is sometimes the wrong question entirely.

Parquet is columnar and binary. It stores each column contiguously, which means a query touching three columns of forty reads only those three. It carries a schema, compresses far better than row-oriented text because similar values sit together, and preserves types exactly.

Where it wins: analytical queries over large datasets, long-term storage of anything sizeable, and any pipeline feeding a data warehouse. Compression ratios against CSV are frequently several-fold, and query performance differences are larger still.

Where it loses: it is not human-readable, it is not appendable in the way JSON Lines is, and it needs a library rather than a text editor. For streaming, for interchange with people, and for small data, text formats remain correct.

A common and sensible architecture: collect to JSON Lines because it is append-friendly and loss-tolerant, then convert to Parquet in batches for analysis and archival. Each format used where its properties help.

Choosing by Job

JobFormatWhy
Web API responseJSONNative to HTTP tooling, types, nesting
Scraped data written incrementallyJSON LinesAppendable, streamable, survives truncation
Sending data to a non-technical colleagueCSVOpens in Excel, which is the actual requirement
ConfigurationNeither — YAML or TOMLComments matter
Large analytical datasetParquetColumnar reads, compression, schema
Bulk database importCSVNative fast-path loaders in most databases
Event or log streamsJSON LinesOne event per line, append-only
Nested or variable-shape recordsJSON or JSON LinesCSV cannot express it without inventing conventions
Data with any user-supplied textJSON or JSON LinesAvoids quoting, delimiter and formula-injection risk

Three rules that resolve most cases without needing the table.

If the data is flat, uniform and going into a spreadsheet or a bulk loader, use CSV. These are genuinely CSV's strengths and nothing else does them as conveniently. Database bulk import in particular is a real advantage — most engines have a fast path for CSV and not for JSON.

If the data is nested, variably shaped, or contains anything a user typed, use JSON or JSON Lines. Flattening nested data into CSV requires inventing a convention, and every convention invented for this has been a source of bugs. Meanwhile, user text contains commas, quotes and newlines, which is exactly what CSV handles least reliably.

If you are writing records continuously, use JSON Lines. Not CSV, because CSV lacks types and you will lose them. Not a JSON array, because it cannot be appended to safely and a crashed process leaves an unparseable file.

People Also Ask

Is JSON better than CSV?

For different jobs, yes and no. JSON is a formal standard with types, nesting and mandatory UTF-8 encoding. CSV is smaller for flat tabular data, streams naturally, and opens in spreadsheets. The stronger claim is that CSV has no formal specification — RFC 4180 says so explicitly — which makes it less predictable across tools.

Why does my CSV file break in Excel?

Usually encoding or delimiter. CSV files do not declare their character encoding, so Excel guesses, and locales using a comma as the decimal separator expect a semicolon delimiter. Both problems are inherent to a format that never specified either. Exporting UTF-8 with a BOM often helps for Excel specifically, at the cost of confusing other parsers.

What is JSON Lines and when should I use it?

One JSON document per line with no wrapping array. Use it whenever you write records incrementally — scraped data, logs, event streams. It streams in constant memory, appends safely, survives truncation with every complete line intact, and keeps full JSON types and nesting.

Is CSV smaller than JSON?

Uncompressed and for flat uniform data, usually by a large margin, because field names appear once rather than per record. After compression the gap narrows sharply, since repeated keys compress very well. If you are storing compressed data, the size argument for CSV is much weaker than raw figures suggest.

Can CSV handle nested data?

Not natively. Any nesting requires a convention you invent — flattening with dotted column names, JSON strings inside cells, or multiple related files. All of these work and all of them mean your CSV is no longer readable by generic tools without your specific convention, which is most of the reason to use CSV in the first place.

Which is faster to parse, JSON or CSV?

CSV, for simple cases, but the comparison is often unfair — a fast split(',') is not a correct CSV parser, and one handling quoting and embedded newlines properly is much closer to JSON in cost. The more important difference is memory: CSV streams row by row while a JSON document generally needs loading whole, which JSON Lines fixes.

Are duplicate keys allowed in JSON?

The specification says names "SHOULD be unique" rather than MUST, so they are technically permitted. It also warns that behaviour is unpredictable when they are not — some parsers keep the last, some error, some fail entirely. Treat duplicates as a bug in whatever produced the document.

What format should I use for scraped data?

JSON Lines, in most cases. Scraped records are frequently nested and variably shaped, which CSV handles badly, and collection is incremental, which JSON arrays handle badly. If the data is genuinely flat and destined for a spreadsheet or bulk load, CSV is fine — and if you write CSV from scraped text, neutralise fields beginning with =, +, - or @ to avoid formula injection.

Wrapping Up

The framing that makes this decision easy is not "structured versus simple". It is that one of these formats has a specification and the other has a description of common practice. RFC 8259 tells you what JSON must do; RFC 4180 tells you what CSV files usually seem to do, and says as much in its own words.

That difference is the source of essentially every CSV problem — undeclared encodings, locale-dependent delimiters, inconsistent quoting, types silently lost through a spreadsheet, and fields that turn into formulas. None of these are bugs in anyone's parser. They are the predictable result of a format that was never fully defined.

For most people writing data rather than reading it, JSON Lines is the answer and is under-adopted. It keeps JSON's types, nesting and settled encoding while removing its one real weakness — it streams, appends safely, and survives a truncated write with every complete record intact. Keep CSV for the two jobs it genuinely does best: handing a flat table to someone who will open it in a spreadsheet, and bulk-loading a database. And if the dataset is large and analytical, neither text format is the right final destination; convert to something columnar and let each format do the job it is shaped for.

JSON vs CSV: What Each Guarantees and When to Use Which | Geonode