JSON vs YAML: Converting YAML to JSON and Back, and the Values That Change on the Way
JSON and YAML describe the same kind of data: maps, lists, strings, numbers, booleans and null. JSON is strict and made for machines. YAML is looser and made for people editing configuration by hand. Converting between them is usually one command, and usually correct. The exceptions are values YAML interprets in ways you did not intend, such as `NO` becoming `false` or `0755` becoming `493`. They convert without any error, so they are worth knowing before you migrate a configuration.
The same data in both formats
{
"service": "api",
"replicas": 3,
"ports": [8080, 8443],
"env": { "LOG_LEVEL": "info", "DEBUG": false }
}
# comments are allowed in YAML
service: api
replicas: 3
ports:
- 8080
- 8443
env:
LOG_LEVEL: info
DEBUG: false
YAML 1.2 was designed so that valid JSON is almost always valid YAML. That is why a YAML parser can read most JSON files unchanged, while the reverse needs a real conversion.
When to use which
Use JSON for data exchanged between programs: API payloads, messages, stored documents, anything generated and parsed by code. It has one way to write each value, parsers are fast and available everywhere, and there is no ambiguity about types.
Use YAML for configuration that people edit and review: CI pipelines, Kubernetes manifests, Docker Compose, Ansible, OpenAPI specifications. Comments, multi-line strings and less punctuation make it easier to read and to diff. The price is a much larger specification, significant indentation and implicit typing, which is the source of the conversion traps below.
A useful rule: if a human writes it, YAML is fine; if a program writes it, use JSON.
Converting YAML to JSON and JSON to YAML
# yq (mikefarah/yq, v4)
yq -o=json config.yaml > config.json
yq -P config.json > config.yaml # -P: pretty YAML output
# Python, with no extra tools beyond PyYAML
python3 -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin), indent=2, default=str))' < config.yaml
// Node.js with js-yaml (v4 implements YAML 1.2)
import { load, dump } from 'js-yaml';
const data = load(fs.readFileSync('config.yaml', 'utf8'));
fs.writeFileSync('config.json', JSON.stringify(data, null, 2));
fs.writeFileSync('back.yaml', dump(data));
Always use the safe loading function: yaml.safe_load in Python, not yaml.load with an unsafe loader, which can construct arbitrary Python objects from tagged input. In js-yaml v4, load is safe by default.
An online YAML to JSON converter is fine for a quick check, but configuration files often contain secrets and internal host names. Prefer one that converts in the browser without uploading the input.
Values that change silently
YAML guesses types from unquoted text, and the rules differ between YAML 1.1 and YAML 1.2. PyYAML, still the most widely used Python library, implements 1.1. This is real output from PyYAML for a small file:
# input PyYAML (YAML 1.1) YAML 1.2 parser
country: NO False 'NO'
version: 1.10 1.1 1.1
mode: 0755 493 (octal) 755
released: 2026-09-28 datetime.date(...) date (in many parsers)
on: true key becomes True 'on'
The "Norway problem": in YAML 1.1, yes, no, on, off, y and n are booleans, so the country code NO becomes false. Even keys are affected, and the on: key in a GitHub Actions workflow becomes True when parsed with PyYAML. Version numbers lose trailing zeros (1.10 becomes 1.1), file modes are read as octal, and dates become date objects that json.dumps refuses to serialise (Object of type date is not JSON serializable).
The fix is the same in every case: quote values that must stay strings, such as "NO", "1.10" and "0755", or use a YAML 1.2 parser such as ruamel.yaml in Python. When converting to JSON, compare a few values by eye, especially country codes, versions, IDs with leading zeros and anything that looks like a date.
What does not survive the round trip
Comments are lost when YAML is converted to JSON, because JSON has no comments. Converting back will not restore them. If the YAML file is the source of truth, keep editing it and generate JSON from it, not the other way round.
Anchors and aliases (&defaults and *defaults, with <<: merge keys) are expanded into full copies. The JSON is correct but larger, and converting it back produces YAML without the shared blocks. Multi-document YAML files, separated by ---, become several JSON documents; yq and most libraries need an explicit option to read all of them. Key order is usually preserved by modern libraries, but do not rely on it for meaning.
In the other direction, JSON to YAML, the risk is output that a YAML 1.1 reader misinterprets later. A good dumper quotes strings like "no" and "0755" automatically; check that yours does.
Validating both formats
Syntax validation catches broken indentation, tabs (YAML forbids tabs for indentation), unclosed quotes and duplicate keys. The YAML specification forbids duplicate keys, but many parsers silently keep the last one. yamllint reports them and enforces style rules; jq empty file.json validates JSON.
Schema validation is the second step: a valid Kubernetes manifest is more than valid YAML. JSON Schema works for both formats, since YAML parses to the same data model, and editors such as VS Code with the YAML extension use it to flag wrong keys and types as you type.
Sources and further reading
The YAML 1.2.2 specification describes the core schema and its differences from YAML 1.1's type resolution. RFC 8259 defines JSON. The PyYAML, ruamel.yaml, js-yaml and yq documentation cover safe loading, YAML versions and output options, and the yamllint documentation describes its checks.
Frequently asked questions
What is the difference between JSON and YAML?
They represent the same data types. JSON is strict, has no comments and is designed for machine exchange; YAML allows comments, multi-line strings and less punctuation, and is designed for humans editing configuration. YAML 1.2 is nearly a superset of JSON.
How do I convert YAML to JSON?
Use `yq -o=json file.yaml`, or in Python `json.dumps(yaml.safe_load(f))`, or js-yaml's `load` plus `JSON.stringify` in Node.js. Check values such as `NO`, `1.10` and `0755`, which YAML 1.1 parsers convert to other types.
Why did NO turn into false when converting YAML?
YAML 1.1 treats `yes`, `no`, `on` and `off` as booleans. Quote the value (`"NO"`) or use a YAML 1.2 parser, which only treats `true` and `false` as booleans.
Are comments kept when converting YAML to JSON?
No. JSON has no comment syntax, so they are dropped and cannot be restored by converting back. Keep the YAML file as the source of truth.
Is every JSON file valid YAML?
Almost always, for YAML 1.2 parsers. Edge cases such as very long keys or certain escape sequences differ, but in practice a YAML 1.2 parser reads JSON files unchanged.
Should I use JSON or YAML for configuration?
YAML if people edit the file by hand and need comments; JSON if the file is generated or consumed mainly by programs. Whatever you choose, validate it against a schema in CI.