Here is a YAML line that appears in a thousand config files:
start: 12:30Convert it to JSON with one popular parser and you get "12:30". Convert the identical line with another and you get 750.
Neither is broken. Both are following a published YAML specification — just different versions of it. That single line is a small demonstration of the real problem: converting YAML to JSON is not a format swap, it is a translation into a language with fewer words, and translations lose things.
This guide covers exactly what goes missing, what quietly changes meaning, and which of it you actually need to worry about.
Every JSON File Is Already YAML
Start with the fact that explains the whole asymmetry: YAML 1.2 is a superset of JSON. Any valid JSON document is already valid YAML, which is why this is a legal YAML file:
{"name": "Alice", "tags": ["a", "b"]}So going the other way — JSON into YAML — is only ever a matter of style. Everything you had still fits, and the output is just easier to read.
Coming back the other direction is not symmetrical. YAML carries features JSON has no equivalent for, so the converter has to decide, for each of them, whether to drop it, flatten it, or refuse. Knowing which is which is the whole job.
Comments Do Not Survive
This is the loss people notice first, and there is no fix for it. JSON has no comment syntax at all — not //, not #, not /* */. It was left out deliberately.
So a config like this:
# Bumped from 3 after the March incident — do not lower
replicas: 5becomes {"replicas": 5}, and the reason anybody chose 5 is gone. The value survives; the knowledge does not.
The practical consequence: treat YAML as the source of truth and JSON as the build output. Convert forwards as often as you like, but do not convert to JSON, delete the YAML, and expect to reconstruct it later. The comments are not coming back.
The Same File, Two Different Answers
Now the one that actually causes incidents. There are two YAML specifications in wide use, and they disagree about what plain, unquoted words mean.
YAML 1.1 (1.1 is what Python's PyYAML and many Ruby tools implement) treats a long list of words as booleans and has some unusual number rules. YAML 1.2 — the current spec, used by the converter on this site — narrowed booleans down to exactly true and false.
These are real results from the same one-line inputs, run through both:
| YAML input | YAML 1.1 gives | YAML 1.2 gives |
|---|---|---|
country: NO | false | "NO" |
v: yes | true | "yes" |
v: on | true | "on" |
v: off | false | "off" |
v: 012 | 10 (read as octal) | 12 |
start: 12:30 | 750 (base-60) | "12:30" |
Look at the last two rows, because they are worse than the booleans.
A version string written 012 becomes 10 under 1.1, because a leading zero once meant octal. And 12:30 becomes 750 — YAML 1.1 supported sexagesimal (base-60) numbers, so a colon-separated value is read as 12 × 60 + 30. A time turns into an integer that looks like nothing in particular.
The country-code case is the famous one, usually called the Norway problem, and it is the same collision seen from the opposite side: converting JSON to YAML safely is about writing quotes so this cannot happen. Reading YAML is about knowing which rulebook your parser is using.
country: "NO", version: "012" and start: "12:30" read identically under every YAML version ever published. Quotes cost you nothing and remove the entire class of problem — and they are worth adding to the YAML itself, not just hoping the converter guesses well.
Anchors Expand — Sometimes Violently
YAML lets you define a block once and reuse it. An anchor &name marks it, an alias *name points back at it, and a merge key <<: folds it into another map. Docker Compose and CI configs lean on this heavily.
JSON has no such mechanism. Every alias must be written out in full, every time. So the file grows:
| A shared block reused… | YAML size | JSON size | Growth |
|---|---|---|---|
| 1 time | 108 bytes | 268 bytes | 2.5× |
| 5 times | 192 bytes | 804 bytes | 4.2× |
| 20 times | 517 bytes | 2,824 bytes | 5.5× |
| 100 times | 2,277 bytes | 13,624 bytes | 6.0× |
Six times bigger is inconvenient, not dangerous. What makes anchors genuinely interesting is that they can nest — an anchored block can itself contain aliases to another anchored block. Then the growth stops being linear:
| Nesting | YAML source | Resulting JSON | Growth |
|---|---|---|---|
| 3 levels × 3 aliases | 80 bytes | 830 bytes | 10× |
| 4 levels × 4 aliases | 118 bytes | 7,573 bytes | 64× |
| 5 levels × 5 aliases | 164 bytes | 93,782 bytes | 572× |
| 6 levels × 6 aliases | 218 bytes | 1,448,987 bytes | 6,647× |
Two hundred and eighteen bytes in, one and a half megabytes out. Extend the same pattern to nine levels and you get roughly 387 million nodes from about 432 bytes of source.
Types JSON Has No Word For
Beyond comments and aliases, YAML has several types that JSON simply cannot express. Each one forces a decision:
| YAML has | Example | What has to happen |
|---|---|---|
| Timestamps | d: 2024-01-15 | Becomes an ISO 8601 string — JSON has no date type |
| Infinity / NaN | v: .inf | JSON cannot hold it. Most tools write null silently |
| Non-string keys | ? [a, b] | Flattened to a string key — JSON keys are always strings |
| Binary data | v: !!binary | Becomes an array of byte values |
| Circular references | an anchor that includes itself | Impossible. JSON has no way to express a cycle |
The .inf row is the one worth watching, because the two big ecosystems fail differently and neither says a word. JavaScript's JSON.stringify turns infinity into null, so a real value quietly becomes a missing one. Python does not do that — it writes Infinity, which is not valid JSON at all, so the file looks fine when you produce it and gets rejected by something downstream. One loses your data, the other produces a file that is not really JSON. That is why a converter is better off refusing than guessing.
Files That Hold More Than One Document
One more thing JSON has no concept of: a single file containing several independent documents, separated by ---.
Anyone who has deployed to Kubernetes has written one — a Service, a Deployment and a ConfigMap stacked in a single manifest. YAML treats those as three separate documents that happen to share a file.
JSON has exactly one root value per document, so a converter has two honest options: emit several JSON files, or wrap the documents in a single array. An array is almost always what you want, because it keeps everything in one place and preserves the original order — which matters when the order encodes deployment sequence.
The reassuring part is that documents do not vanish quietly. Hand a multi-document file to the single-document loader in either js-yaml or PyYAML and both refuse outright, with some version of expected a single document in the stream. The failure is loud.
So the question is not whether your converter drops documents — it is whether it reaches for the multi-document function at all. A tool that throws an error on a perfectly valid Kubernetes manifest is not broken; it is calling the wrong one.
Converting YAML to JSON on CodBolt
- Open the YAML to JSON Converter and paste your YAML, or upload a
.yaml/.ymlfile. - Click Convert. Parsing follows the YAML 1.2 core schema, so
NO,yesand012behave as shown in the 1.2 column above. - If your file holds several documents, the output is a JSON array with one entry per document, and the message under the button tells you how many it found — a quick check that nothing was dropped.
- Anchors, aliases and merge keys are resolved before output, so the JSON contains the full value everywhere an alias appeared.
- Copy or download the result. If the file contains
.infor.nan, you get told where — rather than a silentnull.
The conversion runs inside the page itself. Your config never travels to a server, which matters more than usual here: YAML files tend to be the ones holding hostnames, ports and internal service names.