YAML Lint / Guides

YAML vs JSON

They represent the same data shapes. They're used in completely different places. Here's where each format actually wins, where each falls down, and the small set of rules that prevent every common bug.

Convert YAML to JSON →

The two-line answer

Decision table (skip ahead if you're picking right now)

Your use casePickWhy
HTTP API response bodyJSONEvery framework, WAF, and client library expects it
Kubernetes manifestYAMLkubectl, Helm, Kustomize all speak YAML natively
GitHub Actions / GitLab CI / CircleCI workflowYAMLRequired by the tool — no JSON alternative
Logging / metrics outputJSON (NDJSON)Splunk, Datadog, Loki, Elastic all expect JSON lines
Application config fileYAML or TOMLEditor-friendly; comments matter
OpenAPI / AsyncAPI specEither — both supportedYAML for editing, JSON for tooling
Embedded in a database columnJSONNative column types in Postgres, MySQL, SQLite
Build cache / lockfileJSONMachine-written, never edited by hand

Is "yml" the same as "yaml"?

Yes — .yml and .yaml are both valid file extensions for the same YAML format. The official YAML site recommends .yaml, but .yml is more common in practice (GitHub Actions, Docker Compose, GitLab CI all default to it). Some tools accept only one — Kubernetes manifests are usually .yaml, GitHub workflows are .yml. Lock the extension your tool expects; the parser doesn't care.

Side by side

The same data in both formats:

# YAML
name: my-app
version: 1.0.0
ports:
  - 80
  - 443
config:
  debug: false
  timeout: 30
  # Retry logic was added in v1.0
  retries: 3
// JSON
{
  "name": "my-app",
  "version": "1.0.0",
  "ports": [80, 443],
  "config": {
    "debug": false,
    "timeout": 30,
    "retries": 3
  }
}

Same data tree. YAML drops the braces, brackets, quotes, and commas in exchange for caring about indentation. The # comment in YAML has no JSON equivalent.

Quick syntax differences

FeatureYAMLJSON
Comments# inlineNot allowed
Trailing commasN/ANot allowed
Single quotesAllowedNot allowed
Unquoted keysDefaultNot allowed
Unquoted stringsAllowed (with caveats)Not allowed
Multiline stringsNative (|, >)Use \n in a single-line string
References / aliases& and *None
Multiple documents per fileYes (--- separator)No
Tabs allowed for indentNo (most parsers reject)N/A — no indent
Spec size~80 pages~16 pages

Where YAML wins

Configuration files

Kubernetes manifests, GitHub Actions, Ansible playbooks, Docker Compose, CircleCI configs — all use YAML, all for the same reason: humans read and edit these by hand. JSON's required quotes and commas make it painful for files larger than ~50 lines.

Multiline content

Embedding a SQL query, a shell script, or a long template in JSON means escaping every newline as \n in a single string. YAML's block scalars (| and >) keep the content readable. Multiline strings have their own guide.

Repetition reduction

YAML's anchors (&name) and aliases (*name) let you define a chunk of config once and reuse it. JSON has no equivalent — you copy-paste or use a templating system. Anchors and aliases guide.

Where JSON wins

Speed

JSON parsers are 5-50× faster than YAML parsers. For a 100KB document, Node's built-in JSON.parse typically finishes in under 1ms; the yaml npm package takes 15-40ms for the same bytes. PyYAML's pure-Python parser is the slowest of the bunch (libyaml-backed yaml.CSafeLoader closes the gap). For a config file loaded once at startup, the difference is invisible. For a wire format processing thousands of messages per second, JSON's lead is decisive.

Predictability

JSON has one canonical interpretation. YAML has at least two common ones (1.1 and 1.2) that disagree about whether off means false, whether 010 is octal, and whether unquoted NO is a country code or a boolean. The YAML parser version matters; JSON parsers don't.

Tooling and security

Every WAF, every API gateway, every framework expects JSON in HTTP bodies. YAML parsers have a long history of CVEs (PyYAML's old load(), snakeyaml deserialization) that JSON parsers don't share — JSON is a strictly smaller attack surface.

The four rules that prevent most YAML bugs

  1. Always quote ambiguous strings. Country codes, version numbers, and anything that could be misread as a number, boolean, or null. "on": true not on: true.
  2. Use spaces only, never tabs. Most YAML parsers reject tabs. The error message is rarely helpful.
  3. Pin the YAML version. Use a parser configured for YAML 1.2 if your data has any of: country codes, boolean- looking strings, leading zeros on numbers.
  4. Validate before deploying. Lint the file before checking it in. CI failures two minutes after merge are an avoidable expense.

Conversion

Converting in either direction is straightforward — every YAML construct except anchors maps to a plain JSON shape. Anchors get resolved (and any aliases inlined) during conversion.

Paste your YAML on the home page and toggle to JSON to see the converted output.

Reference

FAQ

Is YAML always slower to parse than JSON?

Yes — by roughly 5-50× depending on the parser and content. JSON's grammar is small enough to parse with a tight state machine; YAML's grammar covers anchors, multiple document streams, type tags, and complex scalar styles. For high-throughput wire formats, JSON wins. For human-edited config, the speed gap rarely matters.

Is every JSON file valid YAML?

YAML 1.2 was designed as a superset of JSON, so a valid JSON document is parsed correctly by a YAML 1.2 parser. The reverse isn't true — most YAML features (comments, anchors, multiline strings, etc.) aren't valid JSON.

What's the 'Norway problem'?

In YAML 1.1, the unquoted string 'NO' (Norway's country code) is parsed as the boolean false, along with 'no', 'off', and 'yes'. YAML 1.2 fixed this by recognizing only 'true' and 'false' as booleans. If your parser is on YAML 1.1 (which the original PyYAML defaulted to for years), country codes break. Quote any string that could look boolean.

Should I use YAML for an API response?

No. Use JSON for wire formats — every language has a built-in JSON parser, security tooling expects JSON, and the parse cost is negligible. YAML's value is for files humans edit (CI configs, Kubernetes manifests, Ansible playbooks).

Why does my YAML config behave differently between tools?

The two most common causes: tab vs space indentation (most parsers reject tabs), and YAML 1.1 vs 1.2 type-coercion differences (Norway problem, Yes/No booleans, octal numbers like 010). Lock the version your tool uses and quote ambiguous strings.

Open the YAML linter →