The short version: JSON for APIs and anything programs exchange, YAML for configuration humans edit, CSV for flat tables going to or from spreadsheets. All three describe data, but they make opposite trade-offs — and because their data models overlap, you can usually convert between them: JSON ↔ YAML and JSON ↔ CSV both run in your browser.
The same record in all three
JSON: {"name": "Ada", "role": "admin", "active": true}
YAML: name: Ada
role: admin
active: true
CSV: name,role,active
Ada,admin,trueWhat actually differs
- Data model. JSON (RFC 8259) and YAML share objects, arrays, strings, numbers, booleans and null — YAML adds anchors, tags and multi-document files. CSV (RFC 4180) has exactly one shape: rows of untyped text fields. In CSV,
trueand01234are just characters. - Comments. YAML has them (
#); JSON and CSV do not. This alone explains YAML's dominance in config files — humans annotate configs. - Ambiguity. JSON has essentially none. YAML has famous foot-guns: unquoted
noparses as a boolean (the “Norway problem”, country codeNO), leading zeros turn into numbers. CSV's ambiguity is dialects: delimiters, quoting and encodings vary by exporting locale — European Excel emits semicolons. - Whitespace. Meaningless in JSON, structural in YAML (indentation is syntax), and significant inside CSV fields.
YAML's power features, and the price
YAML earns its config-file role with features JSON refuses to have. Anchors deduplicate repeated blocks — one definition, reused by reference:
defaults: &defaults retries: 3 timeout: 30 production: <<: *defaults # merges retries and timeout timeout: 60 # then overrides one key
Convert that YAML → JSON and the references vanish into expanded copies — which is also the fastest way to see what your anchors actually produce. The price of YAML's friendliness is implicit typing. This innocent country list:
countries: [DE, FR, NO] # parses as [DE, FR, false] in YAML 1.1 parsers version: 1.20 # the number 1.2 — trailing zero gone zip: 01234 # 1234 in YAML 1.2 — octal 668 in 1.1 parsers
NO is Norway to you and a boolean to a YAML 1.1 parser — the famous “Norway problem”. YAML 1.2 fixed most of this on paper, but widely deployed parsers (libyaml, PyYAML) still follow 1.1 rules. The defensive habit: quote every scalar that must stay a string.
CSV's dialect problem
RFC 4180 nails down commas, CRLF line endings and double-quote escaping ("" inside a quoted field) — but real-world CSV predates the RFC by decades and Excel is its own standard. Concretely: a German or Dutch Excel exports semicolon-separated files (because the comma is the decimal separator there); Excel eats leading zeros unless a column is typed as text; and it historically needed a UTF-8 BOM at the start of the file to render accents correctly. If an “invalid” CSV crosses your desk, check the delimiter and the encoding before blaming the data — then convert it with CSV → JSON once it is comma-separated.
Choose by job, not by taste
Use JSON when programs talk to programs: API payloads, message queues, storage formats, log lines. Every language parses it natively and fast, and its strictness means a document either parses or fails loudly — check any document with the JSON Formatter & Validator.
Use YAML when humans maintain the file: Kubernetes manifests, CI workflows, docker-compose. You get comments, less punctuation noise, and multi-line strings — at the price of the typing foot-guns above. When a YAML config behaves strangely, converting it YAML → JSON shows you what the parser actually understood.
Use CSV when the data is a flat table and a spreadsheet is on either end of the pipeline: exports for analysts, imports from Excel, bulk data loads. It is the only one of the three that non-programmers open directly. Convert a spreadsheet export into objects with CSV → JSON when it needs to enter code.
Converting between them
JSON ↔ YAML is lossless for data (comments and anchors are lost in the YAML → JSON direction, since JSON cannot express them). JSON ↔ CSV is only faithful when the JSON is an array of flat objects with consistent keys — exactly the shape of a table. Round-tripping through CSV strips types: numbers and booleans come back as strings, by design, because guessing corrupts values like postal code 01234.
