The YAML Output
Converting the example JSON produces:
server:
host: 0.0.0.0
port: 8080
ssl: true
database:
url: postgresql://localhost:5432/myapp
pool_size: 10
timeout: 30
logging:
level: info
format: json
outputs:
- stdout
- file
The nested structure maps directly to YAML’s indentation hierarchy. Integers and booleans stay as their native types. Arrays become YAML sequences with - prefix per item.
How JSON Maps to YAML
YAML and JSON represent the same data model: strings, numbers, booleans, null, arrays, and objects. The syntax differences are cosmetic but significant for readability.
| JSON | YAML |
|---|---|
{ "key": "value" } | key: value |
{ "key": 42 } | key: 42 |
{ "key": true } | key: true |
{ "key": null } | key: null |
["a", "b"] | - a\n- b |
| Nested object | Indented block |
JSON requires quotes around all string keys and most string values. YAML allows unquoted strings unless the value would be ambiguous (numbers, booleans, special characters). This is where YAML’s “Norway problem” appears: the country code NO is parsed as the boolean false by YAML 1.1 parsers. Always quote strings that look like booleans or numbers if they are meant to be strings.
When to Use YAML
YAML shows up wherever humans maintain configuration files directly:
Kubernetes and Helm
Every Kubernetes resource is defined in YAML. kubectl apply -f deployment.yaml is the standard workflow. Helm chart values files are YAML. The indentation nesting maps cleanly to Kubernetes’ nested spec structure.
Docker Compose
docker-compose.yml uses YAML for service definitions, volume mounts, port mappings, and environment variables. The comment support is particularly useful here for documenting why a specific port or volume path was chosen.
GitHub Actions
Workflow files in .github/workflows/ are YAML. The multi-line string support (| for literal block, > for folded block) is useful for inline shell scripts in run: steps.
Ansible
Ansible playbooks and inventory files are YAML. The list syntax maps directly to Ansible’s task lists.
When to Use JSON Instead
JSON is better for machine-generated or machine-consumed config:
package.jsonandpackage-lock.json: tooling generates and reads thesetsconfig.json: the TypeScript compiler reads and validates this; it supports comments as a non-standard extension, but the spec format is JSON- API responses: every HTTP client and language has a JSON parser built in or available without extra dependencies
- Data interchange between services: strict syntax means fewer parsing surprises
YAML Gotchas
The Norway Problem
YAML 1.1 (used by PyYAML, Ruby’s psych by default, and many other libraries) treats these unquoted values as booleans:
# These all become booleans in YAML 1.1
enabled: yes
disabled: no
flag: on
toggled: off
Country codes, abbreviations, and short config values are frequent victims. Quote strings that could be misread:
country: "NO"
status: "off"
Indentation with Tabs
A single tab character anywhere in a YAML file causes a parse error. Most editors have a “convert tabs to spaces” setting. Enable it for YAML files.
Multiline Strings
YAML has two block scalar styles for multiline strings. The literal block style (|) preserves newlines:
script: |
#!/bin/bash
echo "hello"
exit 0
The folded block style (>) collapses newlines into spaces (useful for long single-line values split across lines for readability). JSON has no equivalent syntax, so multiline JSON strings (with \n escape sequences) convert to YAML literal blocks when the converter detects embedded newlines.