Skip to content
jsonbeautifiers
English

YAML to JSON

Multi-document streams, and a switch for the YAML 1.1 boolean trap.

YAML
JSON

Nothing you paste leaves your browser. The connect-src allowlist makes that a browser guarantee rather than a promise. Check it yourself

Convert YAML to JSON, with multi-document support and a switch for the typing rules that cause the most confusion.

This direction is where things go wrong, and almost all of it comes down to which version of YAML your other tools implement.

The Norway problem, demonstrated

In YAML 1.1 the bare words no, yes, on, off, y and n are booleans. So a country list containing NO for Norway parses as false. In YAML 1.2 they are ordinary strings.

This matters because the split runs straight through the ecosystem. PyYAML, Ruby Psych and several older tools implement 1.1. js-yaml, Go yaml.v3 and most modern parsers implement 1.2. The same file means different things depending on who reads it.

You can switch the typing rules here and watch a value change in front of you. Measured against js-yaml 5.4.1: `a: no` gives the string "no" under YAML 1.2 and boolean false under YAML 1.1. Even in 1.2 mode, this tool warns when it sees an unquoted no or yes, because the next tool in your pipeline may not agree with it.

The other things YAML has that JSON does not

Comments
Lost, permanently. JSON has no comment syntax. If you maintain the YAML by hand this is a one-way conversion.
Anchors and aliases
Expanded inline. A document using an anchor five times becomes five copies in the JSON, which can be considerably larger.
Timestamps
YAML resolves date-shaped scalars to real dates. JSON has no date type, so they are written as ISO 8601 strings. Choose the JSON typing rules to keep them as plain strings from the start.
Non-string keys
YAML allows a number or even a sequence as a mapping key. JSON does not, so they are converted to strings.
.inf and .nan
No JSON equivalent, so they become null.
Multiple documents
A stream separated by --- holds several documents. By default the first is converted and you are told there were more; turn on all documents to get an array.

Tabs

YAML forbids tabs for indentation, absolutely and with no exceptions. It is the single most common YAML error there is, and it happens because an editor is configured to insert tabs. This tool warns about tabs before it even tries to parse, since the resulting message from any parser is unhelpful.

How to do this in code

Converting in code, and the safety argument that comes with it.

py Python

PyYAML implements YAML 1.1, so this is where "no" becomes False.

import yaml, json

# safe_load, never load. yaml.load can construct arbitrary Python
# objects and has been a real remote-code-execution vector.
data = yaml.safe_load(text)
print(json.dumps(data, indent=2, default=str))

# default=str handles the datetime objects PyYAML produces for
# date-shaped scalars, which json.dumps otherwise refuses.
sh Shell
yq -o=json eval . input.yaml > output.json

# Every document of a multi-document stream
yq -o=json eval-all '[.]' input.yaml
js JavaScript

js-yaml implements YAML 1.2, so "no" stays a string here.

import { load, loadAll } from 'js-yaml';

const data = load(text);              // YAML 1.2 core schema
const docs = loadAll(text);           // multi-document stream
go Go
import "gopkg.in/yaml.v3"

var v any
if err := yaml.Unmarshal(data, &v); err != nil { return err }
out, _ := json.MarshalIndent(v, "", "  ")

Questions

Why did my value become true or false?
You are reading it with a YAML 1.1 parser, where no, yes, on, off, y and n are booleans. Quote the value, or use a YAML 1.2 parser. Switch the typing rules above to see the difference on your own document.
Where did my comments go?
JSON has no comments, so they are dropped. There is no way around it. If the YAML is a file you maintain, keep it as the source of truth and generate the JSON.
Why is yaml.load unsafe in Python?
Because it can instantiate arbitrary Python objects from tags in the document, which makes parsing untrusted YAML equivalent to running it. Always use safe_load.