Skip to content
FireConvert
10 min read

Convert YAML to JSON — comments, the Norway problem, and developer config files

YAML looks like JSON with comments and less punctuation. It isn't. YAML is a different data model — indentation-sensitive, with anchor references, typed scalars that auto-coerce (sometimes wrongly — ask anyone from Norway), multi-document streams, and a 1.1-vs-1.2 split that's still not fully resolved in 2026. Most "yaml to json" conversions work. The ones that don't fail in surprising ways. Here's the honest version: what YAML can express that JSON can't, when the conversion is lossless, when it's lossy, and the specific gotchas that have taken down production deployments.

The short version

  1. Paste or drop your YAML on the converter.
  2. We parse in YAML 1.2 mode (strict) by default — no auto-coercing no to false. Toggle to 1.1 if your source predates 2009 and relies on the old type tags.
  3. Anchors (&name) and aliases (*name) get resolved — the JSON output contains the expanded values inline, since JSON has no reference mechanism.
  4. Multi-document YAML streams (separated by ---) become a JSON array of documents. Single-document streams become a single JSON value.
  5. Comments are stripped. JSON has no comment syntax; there's no lossless place to put them. Our tool optionally embeds them as sibling __comments keys if you need to preserve them.
  6. Download or copy. Pretty-printed with 2-space indent by default; minified option available.

If that covers it, go. The rest of this post is for when your Kubernetes manifest went sideways, your CI config lost its anchor references, or a bare no became false and broke production.

Why devs convert YAML to JSON (and when not to)

YAML is the human-readable config format. JSON is the machine-readable data format. The conversion goes one of four ways:

  • Config file → API payload. Your app reads YAML for humans, serializes JSON for an HTTP API. Happens all over Kubernetes tooling, CI/CD pipelines, and infrastructure-as-code.
  • Editor support. Some tools ship deeper JSON tooling than YAML tooling. Pasting YAML into a JSON editor to inspect structure, then converting back.
  • Schema validation. JSON Schema is more mature than YAML schema tooling. Convert to JSON, run through ajv or similar, get clean error messages.
  • Data interchange. Backend emits YAML logs or config; frontend and most APIs speak JSON. A small conversion layer in the middle keeps both sides happy.

The case for not converting: YAML has comments, anchors, and multi-document streams that JSON can't express. Round-tripping YAML → JSON → YAML loses all three. If editability or commentability of the YAML matters downstream, treat the JSON conversion as a one-way trip.

The Norway problem — YAML 1.1's most famous bug

This is the one every YAML-to-JSON post should open with. In YAML 1.1 (the spec most parsers still default to through 2026), the following unquoted values are parsed as booleans:

y, Y, yes, Yes, YES
n, N, no, No, NO
true, True, TRUE
false, False, FALSE
on, On, ON
off, Off, OFF

Which means this:

countries:
  - US
  - DE
  - NO

Under YAML 1.1 becomes, after conversion:

{
  "countries": ["US", "DE", false]
}

The bare NO (Norway's country code) gets coerced to the boolean false. Same for ON (Ontario), yes as anyone's name or tag, and any bare two-letter abbreviation that happens to match a boolean keyword. This has taken down real deployments.

The fix: YAML 1.2 (released 2009) drops the 1.1 boolean aliases — only true and false are booleans, and only when lowercase. Our tool parses in 1.2 mode by default. If you need the 1.1 coercions for a legacy file, flip the toggle — but know what you're opting into.

Defensive fix: quote any scalar that might match. - "NO" is always a string, in every YAML version, every parser.

Indentation-sensitive syntax — the other foot-gun

YAML uses indentation for structure. JSON uses braces. Which means YAML's parse tree can shift dramatically based on whitespace that looks identical to the eye.

# Looks right
deployment:
  replicas: 3
  labels:
    app: api
    tier: backend

# Different meaning — same text, subtly different indent
deployment:
  replicas: 3
labels:
  app: api
  tier: backend

In the second version, labels is a sibling of deployment, not a child. The JSON output makes this obvious; the YAML source hides it. Tab-vs-space mixing, inconsistent indent levels (2 vs 4), and invisible trailing whitespace are all leading causes of "my Kubernetes manifest doesn't do what I think."

Our tool renders a visual indent guide and flags inconsistent indentation before converting. If your editor isn't already configured for YAML-safe indent (2 spaces, no tabs, trim trailing whitespace), fix that first.

YAML vs JSON — feature parity by the numbers

YAML and JSON overlap heavily but aren't interchangeable. Here's where they diverge on common features:

Feature support in YAML vs JSONCommentsAnchorsMulti-docTypesSizeNoneSomeFullYJYJYJYJYJ
Y = YAML, J = JSON. YAML wins on comments, anchors, multi-doc streams. JSON is slightly more compact (no indentation whitespace) and has a narrower, more predictable type system (no auto-coercion).

Anchors and aliases — the feature JSON can't represent

YAML supports in-document references. Define a node with &name, reference it later with *name:

defaults: &defaults
  timeout: 30
  retries: 3
  log_level: info

production:
  <<: *defaults
  host: prod.example.com

staging:
  <<: *defaults
  host: staging.example.com
  log_level: debug

The <<: merge key pulls all keys from *defaults into the current map. This is common in CI configs (GitLab CI, CircleCI), Kubernetes base manifests before kustomize, and any config that has repeated structure.

JSON has no anchor/alias mechanism. When we convert, the references get expanded inline — every *defaults becomes a full copy of the anchored node. This is lossless semantically (the values are identical) but loses the factoring. Round-tripping back to YAML will produce three fully-expanded blocks, not the anchored version.

If you need reference semantics in a JSON-like format, look at JSON-LD (for linked data) or JSON Schema $ref(for schema reuse). Neither is a drop-in replacement, but they solve adjacent problems.

Multi-document streams

YAML files can contain multiple documents separated by ---. Kubernetes manifests do this constantly:

---
apiVersion: v1
kind: Service
metadata:
  name: api
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api

JSON is a single-document format. Converting a multi-doc YAML stream has three sensible outputs:

  • JSON array — the stream becomes [{service...}, {deployment...}]. Our default. Preserves order, easy to iterate.
  • NDJSON (newline-delimited JSON) — each document on its own line. Easier for streaming consumers and jq.
  • First document only — grab document 0, discard the rest. Occasionally what you want for single-manifest tools.

Types that silently change meaning

YAML 1.1's resolver does implicit type tagging that can surprise you. Besides the Norway problem, watch for:

  • Sexagesimal integers. 10:30:00 in YAML 1.1 parses as 37800 (base-60 seconds). Times in string form need quoting.
  • Leading zeros. 0600 parses as octal (384 decimal) under 1.1. Common in Unix file permissions. Quote or prefix with 0o under 1.2.
  • Scientific notation that isn't. 1e10 is a float; 1-e10 is a string; 1.0 is a float, .inf is infinity. Deserialize carefully.
  • The null tag. Empty values, ~, null, Null, and NULL are all JSON null.
  • Date/time scalars. YAML recognizes ISO 8601 dates as a typed !!timestamp. JSON has no date type — our converter emits an ISO string, which the consumer has to parse.

Kubernetes, Helm, and Ansible — the real-world workflow

90% of the YAML we see in the wild is DevOps config. Common conversion scenarios:

  • kubectl apply input validation. kubectl speaks YAML and JSON; converting to JSON lets you run jq or schema validators before apply.
  • Helm values. Helm charts consume values.yaml. For programmatic generation (from a dashboard, an API), emit JSON — Helm accepts either.
  • Ansible inventories. Ansible reads YAML inventories and var files. For inter-op with tools that speak JSON (Terraform, AWS CLI), convert once and share.
  • CI pipeline debugging. When a CI file fails to parse, converting to JSON and diffing against a known-good snapshot isolates the break.
  • Static analysis. Tools like kubeval, conftest, and opa typically run against JSON internally. Pre-converting saves a round-trip.

How our tool compares (honestly)

YAML-to-JSON is five lines of code in any modern language. What differs is version handling, anchor resolution, multi-doc behavior, and whether the tool warns you about Norway problems before they hit prod.

ToolCostWhere it winsWhere it loses
FireConvertAppFreeYAML 1.2 by default (no Norway problem); anchor + alias resolution surfaced in diff view; multi-document stream handling with array / NDJSON / first-doc modes; comment preservation option as __comments keys; in-browser, no uploadNo YAML-schema validation (we emit; you validate downstream); no Helm template expansion — {{ .Values }} stays literal; no type-coercion override beyond 1.1-vs-1.2 toggle
js-yaml (library)FreeReference JS YAML library; safe/default load modes; anchors resolved; huge ecosystem; what most VS Code extensions use under the hoodLibrary, not a tool — needs wiring; default load() historically unsafe (executes !!js/function tags); need to explicitly use safeLoad or the 4.x load with safe schema
PyYAMLFreePython standard; great for pipelines; supports YAML 1.1 and 1.2 via ruamel.yaml fork; deep integration with Ansible and OpenStackDefault yaml.load() executes arbitrary Python (CVE-worthy) — must use safe_load; 1.1 is default, so Norway problem is latent
yq (CLI, by mikefarah)Freejq-style command-line for YAML; powerful transformations; scriptable; works in CI pipelines; handles multi-doc cleanlyRequires install; two different yq tools exist (Python wrapper vs Go CLI) with different syntax; learning curve for query language
jsonformatter.org YAML toolFree (web)Simple paste-and-convert UX; shows YAML and JSON side by side; wide format supportUploads your paste to their server (not in-browser); ad-heavy; no version toggle; no anchor expansion visibility; no multi-doc handling beyond "first document wins"
onlineyamltools.comFree (web)Clean UI; multiple YAML tools bundled; minimal adsSingle-document only; no anchor resolution surfaced; type coercions opaque; no 1.1-vs-1.2 toggle

Honest summary: if you're running this in a CI pipeline, use yq — it's scriptable, fast, and already installed in most runner images. For ad-hoc interactive work where you want to see what changed, anchor resolution visibly, and a warning when the Norway problem would bite, our YAML to JSON tool is the shorter path.

Tips for the best result

  • Default to YAML 1.2. Unless you're maintaining a 15-year-old config, 1.2 semantics are what you want. Our tool picks this automatically; override only if you know why.
  • Quote ambiguous scalars. "NO" is always a string. "0600" is always a string. "10:30" is always a string. Saves you debug hours later.
  • Inspect anchor expansion before you commit the JSON. If the YAML had three uses of *defaults, the JSON has three inlined copies — fine for consumption, painful for hand-editing.
  • Preserve multi-doc as an array, not first-doc. Discarding later documents is a silent data loss; wrapping as an array preserves everything.
  • Strip comments unless you specifically need them. __comments keys in JSON bloat the output and aren't read by any downstream tool without custom wiring.
  • Pair with a JSON schema validator after conversion. ajv, jsonschema (Python), or our built-in validator catches structural issues the YAML-to-JSON step won't.
  • For infrastructure-as-code, keep YAML as the source of truth. Don't round-trip. Convert on-demand for programmatic consumers; edit the YAML.

Where our tool works well — and where it doesn't

Works well

  • Kubernetes manifests (single or multi-document)
  • GitLab CI, CircleCI, GitHub Actions config
  • Docker Compose files
  • Ansible playbooks and var files
  • Helm values.yaml (template directives stay literal; apply Helm first if you need rendered output)
  • Generic config with anchors, aliases, and merge keys

Doesn't work (well) yet

  • Helm template expansion — we don't run the Go template engine; run helm template first, then convert
  • Custom YAML type tags (!!python/object, !!js/function) — we drop these; they're unsafe to execute in-browser anyway
  • Huge single files (>10 MB) — browser parsers get slow; use yq at the CLI for those
  • YAML 1.2 core vs json vs failsafe schema picker — we default to core (the most common); no UI override yet

Common questions

Is YAML a superset of JSON?

Technically yes in YAML 1.2 — every valid JSON document is a valid YAML 1.2 document. Which means a "JSON to YAML" converter can in principle just emit the JSON unchanged (though that misses the whole point of readability). YAML 1.1 was not a strict JSON superset; some JSON corner cases (like numbers with leading zeros, rare escapes) parsed differently.

What happens to my comments?

Stripped by default (JSON has no comment syntax). Our tool offers an optional __comments sidecar keys mode that preserves them alongside their original keys — useful for round-trip-intent workflows, noisy for straight consumption.

Will my anchors and aliases survive?

Semantically yes — the expanded values end up inline in the JSON. Structurally no — the reference relationship is lost. Round-tripping JSON back to YAML will produce fully-expanded YAML with no anchors.

What's the deal with the Norway problem?

YAML 1.1 auto-coerces bare NO, ON, yes, off, and similar to booleans. Norway's country code is NO, so a list of country codes parses with a false in it. YAML 1.2 fixes this. We default to 1.2. Defensive fix: quote any two-letter bare scalar that could collide.

Can I convert multi-document YAML?

Yes. Multi-document streams separated by --- become a JSON array of documents by default. NDJSON (one document per line) and first-document-only modes also available.

Why is the JSON larger than the YAML?

JSON's syntactic overhead — braces, brackets, commas, quoted keys — typically adds 15-30% to the byte count over an equivalent YAML file. Add expanded anchors and the JSON can be much larger than the original YAML. This is arithmetic, not a bug. If byte size matters, keep YAML.

What about converting JSON back to YAML?

We do that too — see our JSON to YAML tool. It's a simpler problem (no anchors, no types to preserve, no multi-doc), and our converter emits YAML 1.2 with configurable indent and quote style.

Ready?

YAML to JSON →. Paste your YAML, we parse 1.2 by default (no Norway surprises), resolve anchors, handle multi-doc as an array, and give you clean JSON back. Free, in your browser, no upload, no sign-up. For adjacent workflows, our XML to JSON guide covers legacy enterprise configs that still ship in XML, and the Markdown to HTML guide handles the front-matter case when the YAML lives at the top of a .md file. If you're normalizing an entire config folder, our JSON to YAML tool handles the reverse direction when you need to go back to human-readable.