DevToys Pro

free web developer tools

Blog
Rate us:
Try browser extension:
← Back to Blog

YAML Implicit Typing Pitfalls: Booleans, Nulls, and Leading Zeros

14 min read

You convert YAML to JSON and suddenly "yes" becomes true, "07" becomes 7, and "null" becomes null. YAML's implicit type conversion is powerful but can cause unexpected bugs when parsers interpret strings as booleans, numbers, or nulls. This guide explains YAML's type inference rules and how to prevent unwanted conversions.

The Problem: YAML Guesses Types

Unlike JSON, which requires explicit types (strings must be quoted, booleans are true/false), YAML infers types from context. This is convenient but error-prone.

Example: Unexpected Type Conversion

# YAML config file
settings:
  enabled: yes           # Becomes boolean true
  code: 007             # Becomes number 7
  value: null           # Becomes null
  country: NO           # Becomes boolean false!

When converted to JSON:

{
  "settings": {
    "enabled": true,      // Was: "yes"
    "code": 7,            // Was: "007" 
    "value": null,        // Was: "null"
    "country": false      // Was: "NO"
  }
}

The country code NO (Norway) became false because YAML 1.1 treats NO as a boolean. This is the most notorious YAML pitfall.

Boolean Values: More Than True/False

YAML 1.1 recognizes 22 different boolean values. YAML 1.2 simplified this, but many parsers still use YAML 1.1 rules.

YAML 1.1 Boolean Values

True: true, True, TRUE, yes, Yes, YES, on, On, ON, y, Y

False: false, False, FALSE, no, No, NO, off, Off, OFF, n, N

YAML 1.2 Boolean Values (Recommended)

True: true, True, TRUE

False: false, False, FALSE

Real-World Example: Country Codes

# User profile YAML
users:
  - name: Alice
    country: US          # String (not a boolean keyword)
  
  - name: Bob
    country: NO          # YAML 1.1: false (boolean!)
  
  - name: Carol
    country: yes         # YAML 1.1: true (boolean!)

Converted to JSON (YAML 1.1):

{
  "users": [
    {"name": "Alice", "country": "US"},
    {"name": "Bob", "country": false},     // Bug!
    {"name": "Carol", "country": true}     // Bug!
  ]
}

Solution: Quote String Values

users:
  - name: Bob
    country: "NO"        # Explicit string, not boolean
  
  - name: Carol  
    country: "yes"       # Explicit string, not boolean

Now converts correctly:

{
  "users": [
    {"name": "Bob", "country": "NO"},
    {"name": "Carol", "country": "yes"}
  ]
}

Null Values: Many Ways to Express Nothing

YAML recognizes multiple null representations:

  • null, Null, NULL
  • ~ (tilde)
  • Empty value (key with no value)

Example: Null Representations

# All of these become null in JSON
data:
  field1: null
  field2: NULL
  field3: ~
  field4:                # Empty value
  field5:                # Trailing colon, no value

Converted to JSON:

{
  "data": {
    "field1": null,
    "field2": null,
    "field3": null,
    "field4": null,
    "field5": null
  }
}

Pitfall: Unquoted "null" String

# Configuration with nullable field
database:
  password: null         # Null value (no password)
  
api_key: null            # Null value (no API key)

# But what if you literally want the string "null"?
log_level: "null"        # String "null", not null value

Converted to JSON:

{
  "database": {
    "password": null      // Actual null
  },
  "api_key": null,        // Actual null
  "log_level": "null"     // String "null"
}

Leading Zeros: Octal Number Trap

Numbers with leading zeros can be interpreted as octal (base-8) in YAML 1.1.

Example: Octal Conversion

# Configuration with codes
items:
  code1: 007             # Octal 007 = decimal 7
  code2: 010             # Octal 010 = decimal 8
  code3: 077             # Octal 077 = decimal 63
  code4: 100             # Decimal 100 (no leading zero)

Converted to JSON (YAML 1.1):

{
  "items": {
    "code1": 7,           // Lost leading zeros
    "code2": 8,           // Converted from octal
    "code3": 63,          // Converted from octal
    "code4": 100
  }
}

Real-World Problem: Phone Numbers and Zip Codes

# Address book
contacts:
  - name: Alice
    zip: 02134            # Boston zip code
  
  - name: Bob
    zip: 10001            # NYC zip code
  
  - name: Carol
    phone: 07700900123    # UK phone number

Converted to JSON (YAML 1.1):

{
  "contacts": [
    {"name": "Alice", "zip": 1116},        // Bug! Octal 02134 = decimal 1116
    {"name": "Bob", "zip": 4097},          // Bug! Octal 10001 = decimal 4097
    {"name": "Carol", "phone": 534643795}  // Bug! Lost leading zero
  ]
}

Solution: Quote Numeric Strings

contacts:
  - name: Alice
    zip: "02134"          # Explicit string
  
  - name: Bob
    zip: "10001"          # Explicit string
  
  - name: Carol
    phone: "07700900123"  # Explicit string

Now converts correctly:

{
  "contacts": [
    {"name": "Alice", "zip": "02134"},
    {"name": "Bob", "zip": "10001"},
    {"name": "Carol", "phone": "07700900123"}
  ]
}

Hexadecimal Numbers

YAML 1.1 recognizes hexadecimal numbers with 0x prefix:

colors:
  red: 0xFF0000          # Hex number = 16711680
  green: 0x00FF00        # Hex number = 65280
  blue: 0x0000FF         # Hex number = 255

Converted to JSON:

{
  "colors": {
    "red": 16711680,
    "green": 65280,
    "blue": 255
  }
}

If you want to preserve hex strings (e.g., for CSS colors), quote them:

colors:
  red: "#FF0000"         # String
  green: "#00FF00"       # String
  blue: "#0000FF"        # String

Scientific Notation

YAML supports scientific notation for floating-point numbers:

measurements:
  distance: 1.23e5       # 123000
  tiny: 1.23e-5          # 0.0000123
  avogadro: 6.022e23     # 6.022 × 10^23

Converted to JSON:

{
  "measurements": {
    "distance": 123000,
    "tiny": 0.0000123,
    "avogadro": 6.022e+23
  }
}

Infinity and NaN

YAML 1.1 supports special floating-point values:

special_numbers:
  positive_inf: .inf     # Positive infinity
  negative_inf: -.inf    # Negative infinity
  not_a_number: .nan     # NaN (Not a Number)

These convert to special JSON values (implementation-dependent). Most JSON libraries don't support these natively and may serialize them as strings or null.

When to Quote Values

Always quote:

  • Country codes (NO, YES, ON, OFF, N, Y)
  • Version numbers with leading zeros (01.02.03)
  • Phone numbers with leading zeros
  • Zip/postal codes with leading zeros
  • Hex color codes (#FF0000)
  • The literal strings "true", "false", "null", "yes", "no", "on", "off"
  • Numbers that should stay as strings

Don't need to quote:

  • Simple strings without special characters
  • Numbers you want as numbers
  • Actual boolean or null values

Real-World Example: Docker Compose

Docker Compose files are YAML and often hit these pitfalls:

# docker-compose.yml
version: "3.8"           # Quote! Otherwise becomes float 3.8

services:
  app:
    image: node:18
    environment:
      - NODE_ENV=production
      - PORT=3000
      - ENABLE_FEATURE=yes      # Becomes boolean true
      - DEBUG=no                # Becomes boolean false
    ports:
      - "3000:3000"      # Quote! Port mapping string

The environment variables ENABLE_FEATURE and DEBUG become booleans, which may not work if your application expects string values.

Fixed Version

version: "3.8"

services:
  app:
    image: node:18
    environment:
      - NODE_ENV=production
      - PORT=3000
      - ENABLE_FEATURE="yes"    # Explicit string
      - DEBUG="no"              # Explicit string
    ports:
      - "3000:3000"

YAML 1.1 vs YAML 1.2

YAML 1.1 (most parsers):

  • 22 boolean values (yes/no/on/off/y/n)
  • Octal numbers (leading zero)
  • Sexagesimal numbers (60:30 = 3630 seconds)
  • More lenient, more surprises

YAML 1.2 (recommended):

  • Only true/false (case-insensitive)
  • No octal numbers
  • JSON superset (valid JSON is valid YAML)
  • More predictable, fewer surprises

Check your parser's YAML version. Many tools still use YAML 1.1, so it's safer to quote ambiguous values.

Testing YAML Conversions

Use JSON ↔ YAML Converter to test how your YAML converts to JSON. This helps identify unwanted type conversions before they cause bugs.

Test Workflow

  1. Paste your YAML into YAML Converter
  2. Convert to JSON
  3. Check if types match expectations
  4. Add quotes where needed
  5. Re-convert and verify

Quick Reference: Type Inference Rules

YAML ValueInterpreted AsJSON ResultHow to Force String
yesBooleantrue"yes"
noBooleanfalse"no"
onBooleantrue"on"
offBooleanfalse"off"
NOBoolean (YAML 1.1)false"NO"
nullNullnull"null"
~Nullnull"~"
007Octal number (YAML 1.1)7"007"
0x10Hex number16"0x10"
1.23e5Scientific notation123000"1.23e5"
.infInfinityInfinity (special)".inf"

Best Practices

  • Quote ambiguous values - When in doubt, add quotes
  • Test conversions - Use YAML↔JSON converter to verify types
  • Prefer YAML 1.2 - Use parsers that support YAML 1.2 when possible
  • Document your schema - Specify expected types in comments or docs
  • Use linters - YAML linters can warn about implicit conversions
  • Be explicit - Write true/false instead of yes/no

Summary

YAML's implicit type conversion can cause unexpected bugs:

  • yes/no/on/off become booleans
  • null/~/empty values become null
  • Leading zeros trigger octal conversion
  • Country codes like NO become false
  • 0x prefix creates hex numbers

Solution: Quote values when you need explicit strings. Test your YAML conversions with JSON ↔ YAML Converter to catch type issues early.

When working with configuration files, prefer explicit quoting over relying on type inference. It makes your config files more predictable and prevents hard-to-debug type coercion bugs.


Need to convert between JSON and YAML safely? Use JSON ↔ YAML Converter to test conversions and verify types. Also check out JSON Formatter for validating JSON structure after conversion.