Skip to content

JSON vs YAML: Which Format Should You Use for Config Files?

JSON vs YAML for config files — readability, comments, whitespace sensitivity, and when each format is the better choice.

Try it now: YAML to JSON Converter Convert YAML to JSON and JSON to YAML, reformat a config file, and get a line number for the indentation mistake instead of a stack trace.

The Real Question Isn't Which Format Is Better

JSON and YAML represent the same three building blocks — scalars, sequences, and mappings — so a json vs yamldebate framed as “which format is objectively better” goes nowhere. The question that actually has a clear answer is narrower: who is going to read and edit this file, and how often? A file a human opens, edits, and re-reads regularly has different requirements than a file only ever produced and consumed by machines. Get that one distinction right and the choice between the two formats stops being a matter of taste.

This article is a decision framework, not a syntax tutorial — if you need the full depth on YAML's indentation rules, the Norway problem, anchors and aliases, or block scalar styles, that's covered thoroughly in the YAML to JSON conversion guide. Here, the goal is narrower and more practical: lay the two formats side by side across the axes that actually determine which format for config files in a given situation, and give a straight answer instead of a hedge.

JSON vs. YAML: A Head-to-Head Comparison

Six concrete axes, compared directly. Nothing here is a matter of opinion — each row is a factual property of the format's specification.

AxisJSONYAML
CommentsNone. The JSON specification has no comment syntax at all — not a design gap, a deliberate omission.Yes. Anything after a # is a comment, at any nesting level, next to any value.
Verbosity / punctuationEvery object needs braces, every key needs quotes, every sibling needs a comma. Punctuation scales with nesting depth.Nesting is expressed with indentation alone. Keys are unquoted by default. Noticeably less punctuation at depth.
Whitespace significanceNone. Whitespace between tokens is purely cosmetic and can never change what a document means.Significant. Indentation is syntax, the same way it is in Python — reformatting carelessly can change meaning.
Tooling / parser ubiquityA fast, standard-library or near-standard-library parser exists in essentially every language runtime.Usually a third-party dependency, with real behavioral differences between parser versions (1.1 vs. 1.2 rules).
Ambiguity riskEffectively zero. One way to interpret a given document; strings are always quote-delimited.Real, documented risk. Implicit typing can silently coerce a bare word into a boolean or number.
Ways to express the same valueOne. A string is quoted, a null is null, an object is braces.Several. Flow style vs. block style, and multiple equivalent spellings of null (null, ~, or nothing at all after a colon).

Read that table as two clusters, not six unrelated rows. The first two rows are why YAML wins on json vs yaml readabilityfor a hand-authored file. The last four rows are why JSON wins on machine-safety — no whitespace significance, no parser-version drift, no implicit type coercion, and exactly one way to write anything. Neither cluster is wrong; they're optimizing for different readers.

The Same Config, Expressed Both Ways

The readability gap is easiest to see with a real example rather than an abstract claim. Here's one config — a deployment's service definition — written first as JSON, then as equivalent YAML.

deploy-config.json
{
  "service": {
    "name": "payments-api",
    "port": 8443,
    "replicas": 3,
    "timeoutSeconds": 30,
    "featureFlags": {
      "newCheckout": true,
      "legacyBilling": false
    },
    "regions": ["us-east-1", "eu-west-1"]
  }
}
deploy-config.yaml — same data, hand-edited
service:
  name: payments-api
  port: 8443
  replicas: 3
  # Bumped from 15s after the Q2 timeout incident — see INC-4021
  timeoutSeconds: 30
  featureFlags:
    newCheckout: true
    legacyBilling: false # scheduled for removal after the migration
  regions:
    - us-east-1
    - eu-west-1

Both documents parse to the identical value. What differs is entirely about the human who has to maintain the file six months from now. The YAML version carries the reason timeoutSeconds is 30 and not the previous value, and a note that legacyBilling is scheduled for removal — context a JSON file has no syntax to hold at all. Add that context to the JSON version and you either invent a fake "_comment" key that pollutes the actual data, or you lose the context entirely and hope someone remembers, or documents it somewhere else that will inevitably drift out of sync with the file itself.

That's the whole readability argument in one example, and it's worth being precise about what it does notprove: it doesn't make YAML the better data format, only the better authoring format when a human is the one writing the comment in the first place.

The Honest Tradeoff: Flexibility Is Also Ambiguity

It's tempting to stop at “YAML has comments, so YAML wins for config files” — but that skips the cost YAML's flexibility actually carries. Every feature that makes YAML pleasant to hand-write is also a decision a parser has to make on your behalf, and every decision a parser makes silently is a decision that can go wrong silently.

  • Implicit typing. A bare, unquoted word in YAML gets interpreted by type-inference rules the writer may not have consciously invoked — is 3.10 a version string or the number 3.1 with a trailing zero? A YAML parser has to guess; a JSON parser never does, because every JSON string is quote-delimited unconditionally and a number literal is a number literal, with no scalar type inference in between.
  • Multiple ways to express the same value. YAML supports both block style (the indented form used throughout this article) and flow style, a JSON-like { key: value } and [a, b, c]syntax that's valid inline in the middle of an otherwise block-style document. It also accepts several equivalent spellings of null — the literal word null, the tilde ~, or simply nothing at all after a colon. Three ways to write the same absence of a value is three chances for a reviewer to misread one of them, or for two files in the same repository to drift into inconsistent styles for no functional reason.
  • Version-dependent parsing rules.The specific set of bare words a parser treats as booleans differs between the YAML 1.1 and YAML 1.2 specifications, and which one a given library implements is not always obvious without checking. That's a source of behavior that changes depending on which parser processes the same file — something that structurally cannot happen with JSON, where the specification is small enough that implementations don't meaningfully diverge.

None of this is an argument that YAML is broken — it's an argument that its ergonomics and its ambiguity risk are the same coin, not two separate properties you can pick one of. (The specific, frequently-cited case of that ambiguity — the “Norway problem,” where an unquoted country code NO silently becomes the boolean false — is covered in full, with the exact fix, in the YAML to JSON pillar guide.) JSON's strictness is the direct trade for avoiding that entire category of bug: a JSON parser never has to guess what a bare token means, because JSON simply doesn't allow bare tokens where a type could be ambiguous.

When to Pick Each: A Decision Framework

Skip the false balance. Here is the actual, opinionated rule, followed by the reasoning behind it.

Pick JSON when the file is machine-generated, machine-transmitted, or both — and a human never hand-edits it.An API response body, a request payload, a value stored in a database column, a config object serialized by one service and deserialized by another: none of these benefit from comments, because there's no human in that loop to read them. And because nothing about the document's meaning depends on whitespace, it can be minified, reformatted, or piped through any language's standard JSON library without a single edge case to think about. Where a person needs to read a JSON response or config to debug it, that's exactly what a JSON formatter is for — pretty-print it on demand, rather than paying YAML's ambiguity cost in the file at rest.

Pick YAML when the file is hand-authored, long-lived, and benefits from a person occasionally reading it top to bottom. A Kubernetes manifest, a Docker Compose file, a GitHub Actions or GitLab CI pipeline definition, an Ansible playbook — all of these get opened in an editor by an engineer who needs to understand and modify them, sometimes months after they were last touched. The ability to write # why this value is set this waydirectly next to the setting is not a stylistic nice to have in that context; it's the difference between a file that documents its own history and one that requires reconstructing intent from a commit log. The reduced punctuation at depth compounds the same benefit — a 60-line manifest reads as an outline of settings in YAML, not a wall of braces and commas.

The framework collapses to one question worth asking about any specific file in front of you: does a human ever open this file with an editor, on purpose, to understand or change it?If yes, reach for YAML and take advantage of comments. If the honest answer is “never — it's produced by one process and consumed by another,” reach for JSON and take advantage of its total lack of ambiguity instead.

Converting Between the Two When You Need Both

The two formats aren't mutually exclusive within a single system — it's common to author configuration in YAML for the comments and readability, then convert it to JSON at build time for a strict downstream consumer that only accepts application/json. That conversion is necessarily lossy in one specific way: comments have nowhere to go in the JSON output, since JSON has no comment syntax to hold them. Keep the annotated YAML as the source of truth checked into version control, and treat the generated JSON as a disposable build artifact, not the other way around.

GenKitLab's YAML formatter converts in both directions and runs entirely client-side, so a config file with internal hostnames or secrets never leaves your browser. Once a document is in JSON, JSON Formatter & Validator handles the pretty-printing, validation, and diffing that come next. And if the comparison you actually need is JSON against a different format entirely rather than YAML, JSON vs. XML runs through that decision the same way this article ran through JSON vs. YAML.

Frequently asked questions

Should I use JSON or YAML for config files?

It depends on who edits the file. Use YAML for anything hand-authored and long-lived that benefits from comments and occasional top-to-bottom reading — Kubernetes manifests, Docker Compose files, CI pipeline definitions. Use JSON for anything machine-generated or machine-transmitted where a human never hand-edits it, like an API payload or a value passed between services, since comments are meaningless there and JSON's strictness avoids YAML's ambiguity risk entirely.

Why doesn't JSON support comments?

It's a deliberate omission in the specification, not an oversight. JSON's designer has stated the intent was to keep the format minimal and maximally interoperable across parsers, rather than risk different implementations disagreeing on comment syntax. The practical consequence is real, though: a JSON config file has no way to explain why a value is set the way it is, which is the single most-cited reason teams choose YAML for hand-edited configuration instead.

Is YAML more readable than JSON?

For a hand-authored, deeply nested file, yes — less punctuation noise and support for comments make YAML read more like an outline of settings than a wall of braces and commas. That readability comes with a real cost, though: YAML's indentation is syntactically significant and its typing is implicit, so the same flexibility that makes it pleasant to write also introduces ambiguity a JSON document simply can't have.

Is YAML a superset of JSON?

Practically, close to it — valid JSON is valid YAML flow-style syntax in the vast majority of real-world cases, since JSON's braces-and-brackets style is one of the two styles YAML supports. It isn't a strict superset in every edge case across YAML spec versions, but for everyday purposes, any JSON document can be parsed by a YAML parser without modification.

What's a concrete example of YAML's ambiguity risk that JSON avoids?

The clearest case is implicit typing of bare words: an unquoted value like NO, yes, or off can be silently read as a boolean instead of a string, depending on the parser's YAML version. JSON has no equivalent failure mode, because every JSON string is quote-delimited unconditionally — there's no bare-token type inference for a JSON parser to get wrong.

Can I convert between JSON and YAML without losing anything?

Data-wise, yes, in the common case — both formats represent the same scalars, sequences, and mappings, so the underlying values convert losslessly. Comments are the one exception: converting YAML to JSON always drops them, since JSON has no comment syntax to preserve them in. Keep the commented YAML as your source of truth and treat generated JSON as a build artifact.

Which format should an API use — JSON or YAML?

JSON, almost without exception. An API payload is produced by one program and consumed by another; no human hand-edits it in transit, so YAML's comment support and reduced punctuation provide zero benefit. What matters instead is universal, fast, unambiguous parsing across every client language — exactly JSON's strength, and the reason it's the default format for virtually every REST and GraphQL API in production.

Last updated