This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →YAML to JSON
Config & InfraConvert YAML to JSON in your browser. Anchors, merge keys, tags and multiple documents all map to a defined JSON shape or refuse loudly by name — never silently.
YAML style
Reading
The JSON appears here.
Worked example: a docker-compose file with anchors and merges
YAML
# Shared defaults for every service in this stack.
# Edit here once rather than in each service block.
x-common: &common
restart: no
logging:
driver: json-file
version: "3.9"
services:
api:
<<: *common
image: registry.example.com/cave-api:2026.09.12
ports:
- "8080:8080"
worker:
<<: *common
image: registry.example.com/cave-worker:2026.09.12
JSON
{
"x-common": {
"restart": "no",
"logging": {
"driver": "json-file"
}
},
"version": "3.9",
"services": {
"api": {
"image": "registry.example.com/cave-api:2026.09.12",
"ports": [
"8080:8080"
],
"restart": "no",
"logging": {
"driver": "json-file"
}
},
"worker": {
"image": "registry.example.com/cave-worker:2026.09.12",
"restart": "no",
"logging": {
"driver": "json-file"
}
}
}
}
Verified — converting back gives the same 17 values in the same order. 2 aliases expanded, 2 merges applied, 2 comments dropped, 3 values read differently under YAML 1.1.
No network activity while you use this tool Show the numbers
- Requests to any other server
- 0
- Requests since you started typing
- —
- Same-origin requests
- 0
Counted live by your browser's own Performance Timeline — the same data the DevTools Network panel reads. It cannot see what a browser extension does, and it is not meant to replace checking for yourself: here is how, in thirty seconds .
What a YAML reader decides that JSON never has to
JSON's grammar makes a value's type explicit at the syntax level: a string is always in
quotes, a number is always bare digits, true/false/null
are reserved words. YAML instead resolves an unquoted scalar's type from its spelling, and two
real, widely deployed specs disagree about that resolution — YAML 1.1 (SnakeYAML, PyYAML,
go-yaml v2: Spring Boot, Ansible, Kubernetes tooling) and YAML 1.2 core (js-yaml 4, the
yaml npm package, ruamel). Converting YAML to JSON means picking one of those
readings and writing it down as an explicit JSON type — which is exactly the step every
converter that "just" wraps JSON.stringify(yamlLib.load(text)) gets partly wrong,
because it silently inherits whichever spec its underlying library happens to implement.
The two specs and who runs which
| Reader | Spec | Used by |
|---|---|---|
| YAML 1.2 core | 1.2 | js-yaml 4, yaml 2, ruamel.yaml, YamlDotNet, libfyaml, yq (Go) |
| PyYAML | 1.1 | PyYAML, Ansible, Home Assistant, pre-commit, mkdocs |
| SnakeYAML | 1.1 | SnakeYAML, Spring Boot, Jenkins |
| go-yaml v2 | 1.1 | Kubernetes tooling, Helm, kubectl, kustomize |
| go-yaml v3 | 1.2-ish | Compose v2, many Go CLIs |
| Psych | 1.1 | Ruby (stdlib), Rails, GitLab CI |
This tool resolves YAML 1.2 core by default — the modern reading, and what a visitor's mental
model of "YAML" usually is in 2026 — but the Readers tab always shows the YAML 1.1 reading too,
unconditionally, because the honest fact about a bare no in your file is that some
real deployment target reads it as false whether or not you asked to see that.
Anchors, and why the JSON is bigger
An anchor (&common) marks a node for reuse; an alias (*common)
copies it. JSON has no notion of a reference, so every alias becomes a real, independent copy
of the anchored value in the output — which is why a compact YAML file with three services
sharing one anchored block can produce noticeably larger JSON. This is not a flaw in the
conversion; it is what "JSON cannot express sharing" actually means once you write it down.
The receipt counts how many aliases were expanded so the size difference is explained rather
than mysterious.
Merge-key precedence, in one sentence
<<: *base merges base's entries underneath the
mapping's own keys — a key already present in the mapping always wins over the merged-in
value, never the other way around — and <<: [*a, *b] merges left to right,
so an earlier alias in the list wins over a later one where they overlap. This is the detail
most docs state backwards, and it is why the docker-compose worked example above merges
x-common's defaults into both services without either service having to repeat
them.
Multiple documents
A YAML file with one or more --- separators becomes a JSON array by default —
one element per document, in source order — with "first document only" and NDJSON available
as one-click alternatives in the Reading options. This tool refuses to guess: some competing
libraries throw outright on multi-document input rather than offering a shape for it at all.
Tags, and what JSON cannot hold
A core tag like !!str 123 or !!int "12" forces a specific reading
regardless of spelling, and maps directly. !!binary has no JSON byte type, so the
base64 text is kept as written, noted as such. An unrecognised local tag such as
!Env is refused by name and line, with an option to keep the value and drop the
tag instead of guessing what it meant. CloudFormation's own short-form tags (!Ref,
!GetAtt, !Sub and the rest) are the one local-tag family this tool
does map automatically, once a template is detected — see the section below.
CloudFormation short forms
A CloudFormation template written with short-form intrinsic tags — !Ref Bucket
instead of {"Ref": "Bucket"} — is exactly the kind of file the two most
common libraries handle worst: js-yaml throws outright on the unrecognised tag, and
yaml 2 silently drops the tag and keeps only the bare value, which quietly turns
a reference into an unrelated string. This tool auto-detects a CloudFormation template (from
AWSTemplateFormatVersion, or a Resources key together with a
CFN-named tag actually present) and maps every intrinsic — !Ref, !Sub,
!GetAtt, !Join, !If, !Select,
!Split, !FindInMap, !Base64, !Cidr,
!ImportValue, !GetAZs, !Transform,
!Condition, !And, !Or, !Not,
!Equals — to its Fn:: long form. Detection always shows its evidence
as a dismissable badge; it never engages silently.
Doing this from the terminal
-
yq -o=json input.yaml— mikefarah'syqis a 1.2-family reader, so a 1.1-only value (a bareno, a leading-zero octal) resolves differently from what Spring Boot or Ansible would actually construct from the same file. -
python -c 'import yaml, json; print(json.dumps(yaml.safe_load(open("input.yaml"))))'— PyYAML'ssafe_loadis a 1.1 reader (noy/nbooleans, a stricter float pattern), so its answer differs from every 1.2 tool on the same traps, and merge keys resolve differently depending on the PyYAML version. -
node -e "console.log(JSON.stringify(require('js-yaml').load(require('fs').readFileSync('input.yaml','utf8'))))"— js-yaml'sloadrewrites a bare date into a full ISO timestamp with a time component you never wrote, and throws outright on an unrecognised tag rather than mapping or refusing it by name.
Common use cases
- Turning a docker-compose file with anchors and merges into JSON for a config-diffing tool
- Converting a CloudFormation template's short-form tags into their explicit Fn:: shape
- Checking exactly which values a Kubernetes or Ansible reader would resolve differently
- Auditing a multi-document Kubernetes List before splitting it into separate manifests
- Confirming how many comments a YAML file would lose before committing to a JSON pipeline
Frequently asked questions
- Why did no become a string and not false?
- Because this tool resolves YAML 1.2 core by default, and 1.2 core's boolean set is only true/false — no is plain text under 1.2. YAML 1.1 (SnakeYAML, PyYAML, go-yaml v2 — the parsers Spring Boot, Ansible and Kubernetes tooling actually use) reads a bare no as false, and the Readers tab shows that difference unconditionally, whichever spec you pick, because the honest fact about this file is that some real deployment target reads it differently.
- My file has !Ref — why did other tools fail?
- !Ref is a CloudFormation short-form tag, not core YAML — js-yaml 4 throws on an unrecognised tag entirely, and yaml 2 silently drops the tag and keeps only the bare value, which quietly turns {"Ref":"BucketName"} into just the string "BucketName". This tool detects a CloudFormation template (from AWSTemplateFormatVersion or a Resources key together with a CFN-named tag) and maps every intrinsic tag to its Fn:: long form instead, shown as a dismissable badge with the evidence for the detection.
- Where are my comments?
- JSON has no syntax for a comment, so they cannot travel across — but they are not silently discarded either. The Notes tab counts exactly how many were dropped and from which lines, each one a clickable jump back to the source, which is more than the comment report most competing tools give you (most give none at all).
- Why is the JSON in a different order from other tools?
- It isn't — theirs is. Most YAML-to-JSON converters run through a plain JavaScript object in the middle, and `JSON.stringify` on a plain object moves integer-like keys ("2", "10") ahead of alphabetic ones regardless of how they were written. This tool's tree keeps insertion order for every key kind, so a document with keys "10" then "2" prints in that order, matching the file you pasted.
- Multiple documents?
- A YAML file with --- separators becomes a JSON array by default — one array element per document — with "first document only" and NDJSON one click away in the Reading options. NDJSON is the one case an array-of-JSON-values already maps onto multiple documents naturally, which is why it is offered as its own option rather than requiring you to split the array yourself afterwards.
- Is anything uploaded?
- No. The parser, the resolver and the verification all run in this tab's own JavaScript. Nothing is sent to a server, logged, or stored — open the Network tab before you paste to confirm it for yourself.