YAML to JSON Conversion: The Gotchas That Break Your Config Files
Source: Dev.to
YAML and JSON represent the same data structures—objects, arrays, strings, numbers, booleans, and null—so conversion should be straightforward. In practice, YAML’s features and quirks make the process surprisingly treacherous.
Boolean Coercion
YAML automatically interprets certain strings as non‑string types:
country: NOYou expect:
{"country": "NO"}But you get:
{"country": false}YAML treats "NO" as a boolean false. Likewise, "YES" becomes true, "on" becomes true, and "off" becomes false. This is often called the “Norway problem.” To represent the country code for Norway (NO) you must quote it:
country: "NO"Numeric and Date Coercion
Other surprising type conversions:
version: 1.0 # Becomes number 1, not string "1.0"
version: 1.10 # Becomes number 1.1, not string "1.10"
octal: 0777 # Becomes decimal 511 in YAML 1.1
date: 2024-01-15 # Becomes a Date object, not a stringThe version: 1.10 case is especially dangerous: you expect the string "1.10" but get the number 1.1. In version comparisons, 1.1 and 1.10 are very different. The fix is to quote strings that might be misinterpreted:
version: "1.10"Multiline Strings
YAML offers several multiline string syntaxes:
# Literal block (preserves newlines)
description: |
Line one
Line two
Line three
# Folded block (joins lines with spaces)
description: >
This is all
one paragraph
on one line.
# With chomp indicators
trailing_newline: |+
Keeps trailing newlines
no_trailing: |-
No trailing newlineJSON has no multiline string syntax; all newlines must be escaped as \n.
Literal block (|) becomes:
{"description": "Line one\nLine two\nLine three\n"}Folded block (>) becomes:
{"description": "This is all one paragraph on one line.\n"}The trailing‑newline behavior (default: single trailing newline, + to keep all, - to strip) matters for exact string matching and must be handled correctly.
Comments
YAML supports comments; JSON does not.
# This is a database configuration
database:
host: localhost # Change for production
port: 5432Converting to JSON drops all comments:
{
"database": {
"host": "localhost",
"port": 5432
}
}This is a one‑way data loss. If you convert YAML to JSON and back, the comments are gone—problematic for configuration files where comments provide essential context.
Anchors and Aliases (References)
YAML allows reuse of mappings via anchors and aliases:
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
host: prod.example.com
staging:
<<: *defaults
host: staging.example.com&defaultsdefines an anchor.*defaultsreferences it.<<merges the referenced mapping.
JSON has no equivalent, so the converter must resolve all references inline:
{
"defaults": {"timeout": 30, "retries": 3},
"production": {"timeout": 30, "retries": 3, "host": "prod.example.com"},
"staging": {"timeout": 30, "retries": 3, "host": "staging.example.com"}
}The data is duplicated in the JSON output, increasing file size and eliminating the single‑source‑of‑truth benefit.
Ordering
Both YAML mappings and JSON objects are unordered by specification, but in practice YAML files are written in a deliberate order that humans expect to be preserved. Most converters preserve insertion order, but this is not guaranteed.
A Robust Converter
I built a YAML‑to‑JSON converter that handles all these edge cases:
- Boolean coercion warnings
- Multiline string conversion
- Anchor resolution
- Comment stripping (with a warning)
You can try it at zovo.one/free-tools/yaml-to-json-converter. It also supports JSON‑to‑YAML conversion for the reverse direction.