JsonMind
JSON & Data12 min readUpdated Nov 9, 2026

JSON vs YAML: Differences, Pitfalls and When to Use Each

Compare JSON and YAML syntax, comments, anchors, data types and tooling. Learn when each format fits APIs, configuration, CI and Kubernetes.

JMBy JsonMind EngineeringLast reviewed: Nov 9, 2026Reviewed against primary specifications and linked sources.
Quick answer

JSON is stricter, easier to parse safely and the default for APIs. YAML is easier for humans, supports comments and anchors, and is common in configuration and Kubernetes. Convert between them when the consumer requires a specific format, then validate the result because YAML features such as comments, anchors and multiple documents have no direct JSON equivalent.

Key takeaways
  • JSON and YAML represent similar data but have different syntax and safety profiles.
  • YAML supports comments, anchors and multiple documents; JSON does not.
  • YAML's implicit typing can surprise you: unquoted yes, no, on and off may become booleans.
  • Use a real parser for both formats; do not parse YAML with regular expressions.
  • Treat YAML from untrusted sources as code, not data, and use a safe loader.

JSON and YAML often appear side by side: a JSON API response, a YAML deployment file, a JSON Schema stored as YAML. They can represent similar data, but they are not interchangeable in syntax, safety, or tooling.

This guide compares them where it matters and shows how to convert without losing meaning.

The useful question is not which format is "better" but which failure modes you can tolerate. JSON fails loudly and predictably; YAML fails quietly through implicit typing, indentation, and anchors. Pick the failure mode that matches who edits the file and who parses it.

The same data in both formats

{
  "service": "api",
  "replicas": 3,
  "enabled": true,
  "ports": [80, 443]
}
service: api
replicas: 3
enabled: true
ports:
  - 80
  - 443

The data is the same. The syntax is not. YAML relies on indentation and line breaks; JSON relies on braces, brackets, commas and quotes.

The two snippets produce the same tree only because every value is unambiguous. Change one line to version: 1.20 and the YAML parser may hand you the number 1.2, while the JSON equivalent "version": "1.20" stays a string. YAML also accepts flow style β€” {service: api, replicas: 3} β€” which looks like JSON but follows YAML's quoting and typing rules. Do not assume that because a line looks like JSON, it parses like JSON.

Syntax differences that matter

FeatureJSONYAML
CommentsNot supportedSupported with #
Quotes around keysRequiredOptional
Trailing commasNot allowedNot applicable
IndentationIrrelevantSignificant
Multiple documentsNot supportedSupported with ---
Anchors and aliasesNot supportedSupported with & and *
Explicit typesLimited to JSON typesTags and implicit resolution
Duplicate keysBehavior varies by parserSpec says unique, parsers vary
TabsAllowed as whitespaceForbidden for indentation
Parser complexityLowerHigher

JSON's smaller grammar is a feature. It is easier to parse, easier to validate, and less likely to hide ambiguity.

Duplicate keys deserve their own warning. RFC 8259 says names should be unique but does not mandate an error, so one parser keeps the last value, another keeps the first, and a third rejects the document. YAML requires unique keys in the specification, yet many parsers silently overwrite. In both formats, a duplicate key is a data-loss bug waiting for the wrong tool. Lint for it before the file reaches production.

Tabs are another quiet difference. JSON treats a tab as whitespace anywhere, while YAML forbids tabs for indentation but allows them inside quoted scalars. A file that looks aligned in an editor with tab width 4 can fail to parse in CI, or worse, parse differently when someone converts tabs to spaces.

YAML features with no JSON equivalent

Comments

replicas: 3 # keep this in sync with the HPA

JSON has no comments. A JSON converter will drop the comment, and the explanation disappears. If comments are important, keep the YAML source as the source of truth and generate JSON as a build artifact.

JSONC and JSON5 add comments for configuration files such as tsconfig.json and editor settings, but they are not standard JSON. Sending them to an API that calls JSON.parse fails, often with a confusing error pointing at the comment rather than the real problem. A comment is also not enforcement: if a comment says "do not raise this above 10," add a schema constraint or a test, because the next editor may not read it.

Anchors and aliases

defaults: &defaults
  timeout: 30
  retries: 3

production:
  <<: *defaults
  timeout: 60

Anchors reduce repetition. JSON has no merge keys, so a converter must expand every alias. The resulting JSON is larger and no longer expresses the shared structure.

Two details bite in practice. First, the << merge key is a YAML 1.1 type, not part of the YAML 1.2 core schema; some parsers support it, some require a flag, and some ignore it silently. Second, aliases are expanded at parse time, so the parsed tree has no notion of shared identity. A converter that expands a 10 MB YAML file with heavily reused anchors can produce a 100 MB JSON document, and an alias bomb can expand exponentially. Set an alias-expansion limit, and do not use anchors as a substitute for a schema or a template engine.

Multiple documents

---
kind: Deployment
---
kind: Service

YAML streams can contain multiple documents. JSON files contain one value. A converter must decide whether to produce an array, a wrapper object, or reject the input.

Those choices are not equivalent. An array loses per-document metadata such as the source file or index; a wrapper object changes the shape clients expect; taking only the first document silently drops the rest. Kubernetes manifests rely on ---, so a converter that stops after one document is a data-loss bug. Watch for --- inside a block scalar too: a line of dashes in a shell script or certificate should not start a new document, and a parser that confuses the two will split a value in half.

YAML typing surprises

YAML resolves unquoted scalars into types. That is convenient until it is not.

country: NO
enabled: yes
version: 1.20

In YAML 1.1, NO may become false, yes becomes true, and 1.20 becomes the number 1.2. The "Norway problem" is the classic example. The safe rule is to quote values that must remain strings:

country: "NO"
version: "1.20"

YAML 1.2 narrows implicit boolean resolution, but parser behavior varies. Quoting is portable and explicit.

The catalog of surprises is longer than the Norway problem. In YAML 1.1, an unquoted 12:30 can be parsed as the base-60 integer 750, 012 as octal 10, and 1_000 as 1000. Values such as .inf, .nan, ~, and the empty string resolve to special numbers or null. Some parsers convert 2026-11-09 into a date object, which then serializes to JSON as a timestamp in UTC and may shift the day. And the on: key in GitHub Actions is a famous casualty: under YAML 1.1 rules it becomes the boolean true, which is why tools and documentation treat it specially.

The practical rule is broader than booleans: quote any scalar whose type matters. Versions, phone numbers, ZIP codes, account IDs, dates, times, and keys that look like booleans should all be quoted. Run a linter with a declared schema version, and pin the parser version in CI, because upgrading a YAML library can change how existing files parse.

JSON limitations

JSON is intentionally small. It has no comments, no dates, no binary type, and no references. Dates are strings, binary data is usually Base64, and shared structures are repeated.

These limitations make JSON predictable. A JSON parser does not need to guess whether NO is a string or a boolean.

Two JSON limits deserve explicit handling. Numbers are IEEE 754 doubles in most parsers, so integers above 2^53 lose precision; a 19-digit database ID becomes a different number when parsed in JavaScript. Send such IDs as strings, or use a parser with big-integer support. And JSON has no streaming value separator: JSON Lines (one object per line) is a convention, not part of the standard, but it is the practical choice for logs and large exports because it lets consumers process one record at a time.

JSON's strictness is also a security advantage. JSON.parse does not construct objects, call functions, or resolve references; the dangerous part is what application code does with the result, such as merging untrusted keys into an object and triggering prototype pollution.

Conversion pitfalls

When converting JSON to YAML:

  • Key order is usually preserved by modern libraries, but do not rely on it for semantics.
  • Strings that look like numbers or booleans should be quoted in the YAML output.
  • Large integers may be emitted in scientific notation by some libraries; check the output.
  • Unicode is usually preserved, but escape sequences may change.

When converting YAML to JSON:

  • Comments are lost.
  • Anchors and aliases are expanded.
  • Multiple documents must be combined or rejected explicitly.
  • Custom tags may be unsupported.
  • Implicit types may change if the converter uses different YAML rules.

Concrete failure cases are worth testing. A YAML value enabled: yes becomes JSON true, not "yes". An unquoted version: 1.20 becomes 1.2, losing the trailing zero that version comparisons rely on. A block scalar using | keeps its final newline while > folds lines and may drop it, so a checksum or PEM block can change. YAML !!binary may turn into a Base64 string, an array of bytes, or an error depending on the converter. A date parsed into a language-native date becomes a UTC timestamp, shifting the calendar day for users east of Greenwich.

Always validate the converted output. For JSON, use a JSON formatter and validator. For YAML, use a YAML formatter and validator. The JSON ↔ YAML converter is useful for one-off conversions, and the Kubernetes YAML inspector helps review manifests before applying them.

When to use JSON

  • API request and response bodies.
  • Data exchanged between services.
  • Browser storage and configuration.
  • Cases where a small, strict grammar and fast parsing matter.
  • Public contracts where ambiguity is unacceptable.

When to use YAML

  • Human-edited configuration.
  • CI/CD pipelines.
  • Kubernetes manifests and Helm values.
  • Files where comments and shared anchors improve readability.
  • Cases where the file is reviewed and maintained by people.

YAML is a configuration language; JSON is a data interchange format. Using YAML for an API payload works, but it adds parser complexity and typing surprises for little benefit.

That recommendation has a reverse side. Using JSON for human-maintained configuration is also a poor fit: no comments, mandatory quoting, no anchors, and error messages that point at a byte offset rather than a line. YAML is the better default when a person edits the file weekly; JSON is the better default when a program writes and reads it. OpenAPI is a common middle ground: the specification is often authored in YAML and published as JSON, with the YAML as source and the JSON as a generated artifact.

Security: parsing untrusted YAML

YAML is more than data in many languages. Tags can construct objects, and anchors can expand exponentially. A malicious YAML file can cause denial of service or instantiate unexpected classes.

Rules:

  1. Use a safe loader that only produces maps, lists and scalars.
  2. Set limits on document size, nesting depth and alias expansion.
  3. Never deserialize untrusted YAML into application objects.
  4. Prefer JSON for untrusted network input.

JSON parsers have their own limits, but the attack surface is smaller because the grammar does not include object construction.

The unsafe-loader problem is language-specific but the pattern is universal. A loader that instantiates arbitrary classes from tags lets a document choose which application code runs during parsing; a YAML file from a user or a third-party integration should never reach that loader. Even a safe loader needs resource limits, because anchors and deeply nested structures can exhaust memory or the call stack. Treat parsing as untrusted input handling: enforce a maximum document size, a maximum depth, and a maximum number of aliases, and run the parser in a process with a memory limit.

JSON is not automatically safe either. It avoids code execution during parsing, but a deeply nested document can still cause stack exhaustion, and a huge document can exhaust memory. Apply size and depth limits to both formats; the difference is that YAML also has to defend against object construction.

A practical conversion workflow

  1. Identify the source of truth: YAML for configuration, JSON for API data.
  2. Convert in one direction and store the result as an artifact.
  3. Validate the output with the target format's validator.
  4. Diff the converted result against the previous version.
  5. Keep comments and anchors in the source, not in the generated file.
  6. Add the conversion to CI so it is reproducible.

The JSON to YAML converter handles the common cases. For Kubernetes, review the converted manifest with the Kubernetes YAML inspector before applying it.

In CI, make the conversion reproducible: pin the converter version, store the generated file, and fail the build when regenerating produces a diff. Validate the generated artifact against a schema rather than only checking that it parses, and keep a few golden files that cover anchors, multi-document input, and quoted scalars. Never hand-edit a generated file; the next build will overwrite it, and the two sources of truth will drift.

The short version

SituationBetter choiceWhy
Public API payloadJSONStrict grammar, broad client support
Human-edited deployment configYAMLComments, anchors, readable diffs
Machine-generated configEitherJSON is simpler to emit safely
Logs and large exportsJSON LinesOne record per line, streamable
Untrusted network inputJSONNo tag-based object construction
Files needing review commentsYAMLComments survive review

Use JSON when machines exchange data and strictness matters. Use YAML when humans maintain configuration and comments matter. Convert deliberately, validate both sides, and quote strings that look like booleans or numbers.

The recommendation is wrong when it ignores the team's actual tooling. A Kubernetes-only shop should not introduce JSON manifests just for purity; a frontend team already using JSONC for configuration should not migrate to YAML for comments it already has. And bidirectional sync between the two formats is almost always a mistake: pick one source of truth, convert in one direction, and keep the generated output out of manual editing.

Frequently asked questions

Is YAML a superset of JSON?

YAML 1.2 is designed to be a superset of JSON, so many JSON documents are valid YAML. The reverse is not true: YAML comments, anchors, tags and multiple documents have no direct JSON representation.

Why does YAML turn yes into true?

YAML 1.1 resolves unquoted yes, no, on and off as booleans. YAML 1.2 narrows this, but many parsers still follow 1.1 behavior. Quote values that look like booleans when you mean strings.

Can I put comments in JSON?

No. Standard JSON does not support comments. JSON5 and JSONC add comments for configuration use cases, but they are not standard JSON and should not be sent to APIs that expect JSON.

Which format is faster to parse?

JSON parsers are usually faster and simpler because the grammar is smaller. YAML parsing involves more work, including indentation and implicit type resolution. For high-volume APIs, JSON is the better choice.

Is YAML safe to parse from untrusted input?

Not with a loader that constructs arbitrary objects. YAML tags can reference application classes in some languages. Use a safe loader that only produces maps, lists and scalars, and set size and depth limits.

References

Put this guide into practice

Browse all tools

Open the browser tool. Inputs stay in your browser and are not uploaded to the business server.

Related guides

All guides