Basic Syntax
Feature | Description | Example |
---|
Indentation | YAML uses indentation (spaces, not tabs) for structure |
parent:
child: value
another_child: value |
Comments | Comments start with a pound/hash symbol |
# This is a comment
key: value # This is an inline comment |
Key-Value Pairs | The basic building block of YAML documents |
key: value
server: apache
port: 80 |
Case Sensitivity | YAML is case-sensitive |
Name: John
name: john # These are different keys |
Scalars (Strings, Numbers, Booleans, Null)
Type | Description | Example |
---|
Strings | Plain text, with optional quotes |
unquoted: Hello World
single_quoted: 'Hello World'
double_quoted: "Hello World" |
Numbers | Integers and floating points are parsed automatically |
integer: 42
float: 3.14159
scientific: 12.3015e+05
octal: 0o14 # = 12 decimal
hex: 0xC # = 12 decimal
infinity: .inf
negative_infinity: -.inf
not_a_number: .nan |
Booleans | True/false values have multiple representations |
boolean_true: true # Also True, TRUE, yes, Yes, YES, on, On, ON
boolean_false: false # Also False, FALSE, no, No, NO, off, Off, OFF |
Null | Null or undefined values |
null_value: null # Also Null, NULL, ~, or simply nothing
explicit_null: ~
empty:
key_with_no_value: |
Collections (Lists and Dictionaries)
Type | Description | Example |
---|
Lists (Block Style) | Sequences of items with hyphen-dash notation |
fruits:
- Apple
- Banana
- Orange |
Lists (Flow Style) | Lists can be written in a JSON-like inline style |
fruits: [Apple, Banana, Orange] |
Dictionaries (Block Style) | Mappings with key-value pairs |
person:
name: John Doe
age: 30
languages:
- Python
- JavaScript |
Dictionaries (Flow Style) | Dictionaries can be written in a JSON-like inline style |
person: {name: John Doe, age: 30, languages: [Python, JavaScript]} |
Nested Collections | Lists and dictionaries can be nested |
departments:
- name: Engineering
employees:
- name: Alice
role: Developer
- name: Bob
role: DevOps
- name: Marketing
employees:
- name: Charlie
role: Content Writer |
Anchors and Aliases
Feature | Description | Example |
---|
Anchors (&) | Create reusable blocks of configuration |
base: &base
name: Base Config
timeout: 60
retries: 5 |
Aliases (*) | Reference anchors to reuse their values |
development:
<<: *base # Merges the base anchor
environment: development
debug: true
production:
<<: *base # Merges the base anchor
environment: production
debug: false |
Overriding Values | Override specific values from anchors |
defaults: &defaults
timeout: 30
logging: true
testing:
<<: *defaults
timeout: 10 # This value overrides the one from defaults |
Multiple Anchors | Merge multiple anchors |
common: &common
version: 1.0
api_key: abc123
logging: &logging
log_level: info
log_format: json
config:
<<: [*common, *logging] # Merge multiple anchors
environment: production |
Data Types
Type | Description | Example |
---|
String | Text data that can be quoted or unquoted |
name: John Doe
job: "Software Engineer" |
Integer | Whole numbers |
age: 30
year: 2023 |
Float | Floating point numbers |
pi: 3.14159
gravity: 9.81 |
Boolean | True/false values |
active: true
disabled: false |
Null | Empty or undefined values |
value: null
empty: ~ |
Timestamp | Date and time (ISO-8601 format) |
created: 2023-01-15T12:30:45+00:00
date: 2023-01-15 |
Binary | Binary data (using !!binary tag) |
gif_file: !!binary |
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
OTk6enp56enmleECcgggoBADs= |
Sets | Collections of unique values (using !!set tag) |
fruits: !!set
? apple
? banana
? orange |
Multiline Strings
Style | Description | Example |
---|
Literal Block (|) | Preserves line breaks; indentation is stripped |
description: |
This is a multi-line string.
Line breaks are preserved.
Indentation is stripped.
Extra indentation is preserved. |
Folded Block (>) | Folds line breaks into spaces; preserves empty lines |
description: >
This is a multi-line string.
Line breaks become spaces.
Empty lines create line breaks. |
Block Chomping (+) | Keeps all trailing line breaks |
text: |+
This text has trailing line breaks.
# The three empty lines above are preserved |
Block Chomping (-) | Strips all trailing line breaks |
text: |-
This text has no trailing line breaks.
# No line breaks are preserved |
Indentation Indicator | Specifies the exact number of spaces to strip |
code: |2
def hello():
print("Hello, world!")
# The function is indented by 4 spaces, and 2 spaces are stripped |
Special Characters Escaping
Character | Description | Example |
---|
Quotes in Strings | Escaping quotes in quoted strings |
single_quote: 'It''s a nice day'
double_quote: "She said, \"Hello!\"" |
Backslash | Escaping backslashes in strings |
windows_path: "C:\\Program Files\\App"
windows_path_literal: 'C:\Program Files\App' |
Special Chars in Double Quotes | Control characters in double-quoted strings |
newline: "Line 1\nLine 2"
tab: "Column 1\tColumn 2"
unicode: "Pi: \u03C0" |
Colon in Unquoted Strings | Colons need space afterwards in unquoted strings |
valid: http://example.com # Space after colon in URL
invalid_without_quotes: http://example.com:8080 # Would need quotes
valid_with_quotes: "http://example.com:8080" |
Special Values | Values that need quoting to be treated as strings |
numeric_string: "123" # Quoted to ensure it's a string, not a number
boolean_like: "yes" # Quoted to prevent parsing as boolean true
null_like: "null" # Quoted to prevent parsing as null |
Document Structure
Feature | Description | Example |
---|
Document Start | Marks the beginning of a document |
---
# Document content starts here
key: value |
Document End | Marks the end of a document |
key: value
# Document content ends here
... |
Multiple Documents | Multiple documents in a single file |
---
# First document
name: Document 1
---
# Second document
name: Document 2
---
# Third document
name: Document 3
... |
Directives | Special instructions at the start of a document |
%YAML 1.2
---
# Document with YAML 1.2 directive |
Complex Structures
Structure | Description | Example |
---|
Nested Maps and Lists | Complex nesting of dictionaries and lists |
company:
name: Example Corp
departments:
- name: Engineering
employees:
- name: Alice
skills:
- Python
- Kubernetes
- name: Bob
skills:
- Go
- AWS
- name: Marketing
employees:
- name: Charlie
campaigns:
q1:
budget: 50000
channels: [Social, Email]
q2:
budget: 65000
channels: [Social, PPC] |
Complex Mapping Keys | Using complex structures as keys |
? - Manchester United
- Chelsea
: 2-0
? - Barcelona
- Real Madrid
: 3-2 |
Merging Multiple Maps | Using anchors and aliases to merge multiple maps |
defaults: &defaults
port: 80
timeout: 60
retries: 3
development:
<<: *defaults
host: dev.example.com
debug: true
production:
<<: *defaults
host: prod.example.com
timeout: 30 # Override specific value
tls: true # Add new value |
Combining Flow and Block Styles | Mix both styles in the same document |
servers:
- name: server1
config: {port: 8080, protocol: http}
roles: [api, web]
- name: server2
config:
port: 8443
protocol: https
roles:
- database
- cache |
Tags and Type Casting
Tag | Description | Example |
---|
Explicit String | Force a value to be interpreted as a string |
number_as_string: !!str 123
boolean_as_string: !!str true |
Explicit Integer | Force a value to be interpreted as an integer |
integer: !!int 42
string_to_int: !!int "42" |
Explicit Float | Force a value to be interpreted as a float |
float: !!float 3.14
integer_to_float: !!float 42 # Becomes 42.0 |
Explicit Boolean | Force a value to be interpreted as a boolean |
bool_from_string: !!bool "true" # Becomes true
bool_from_number: !!bool 1 # Becomes true
bool_from_zero: !!bool 0 # Becomes false |
Null | Force a value to be interpreted as null |
null_value: !!null
explicit_null: !!null "null" # Still null |
Sequence/List | Force a value to be interpreted as a sequence |
empty_list: !!seq {}
single_value_list: !!seq 1 # Becomes [1]
string_to_chars: !!seq "abc" # Becomes ['a', 'b', 'c'] |
Mapping/Dictionary | Force a value to be interpreted as a mapping |
empty_map: !!map []
pairs_to_map: !!map [[key1, val1], [key2, val2]] |
Binary | Interpret a value as binary data (base64) |
binary_data: !!binary |
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
OTk6enp56enmleECcgggoBADs= |
Timestamp | Interpret a value as a timestamp |
iso_datetime: !!timestamp 2023-01-15T12:30:45+00:00
iso_date: !!timestamp 2023-01-15 |
Sets | Create a set of unique values |
unique_items: !!set
? apple
? banana
? apple # Duplicate, will only appear once |
Ordered Maps | Create a mapping that preserves key order |
ordered: !!omap
- first: 1
- second: 2
- third: 3 |
Custom Tags
Feature | Description | Example |
---|
Local Tags | Custom tags that are specific to a document |
%TAG !local! !my-app/
---
# Now !local! will be expanded to !my-app/
person: !local!person
name: John
age: 30 |
Global Tags | Custom tags that follow a URI convention |
%TAG !yaml! tag:yaml.org,2002:
---
# Using globally defined tags
integers: !yaml!int [1, 2, 3] |
Application-Specific Tags | Custom tags for application-specific data types |
configuration: !config
environment: production
features:
- !feature
name: dark-mode
enabled: true
- !feature
name: analytics
enabled: false |
Tag Shorthand | Using shorthand notation for tags |
%TAG !e! tag:example.com,2023:
---
# This:
value: !e!type {}
# Is equivalent to:
value: !tag:example.com,2023:type {} |
Directives
Directive | Description | Example |
---|
YAML Version | Specifies the YAML version to use |
%YAML 1.2
---
# This document uses YAML 1.2 |
TAG Directive | Defines tag shortcuts |
%TAG !yaml! tag:yaml.org,2002:
%TAG !app! tag:myapplication.com,2023:
---
numbers: !yaml!seq [1, 2, 3]
user: !app!user
name: John |
Directive End Marker | Marks the end of directives and start of document |
%YAML 1.2
%TAG !yaml! tag:yaml.org,2002:
--- # Directive end marker
# Document content starts here |
Best Practices
Practice | Description | Example |
---|
Consistent Indentation | Use consistent indentation (2 spaces recommended) |
# Good
parent:
child1: value
child2:
grandchild: value
# Avoid inconsistent indentation
parent:
child1: value
child2:
grandchild: value |
Quote Complex Strings | Quote strings that could be misinterpreted |
# Good (quoted to avoid misinterpretation)
message: "Error: file not found"
empty_string: ""
numeric_string: "123"
# Problematic (could be misinterpreted)
message: Error: file not found # Colons need care
empty_string: # This is a null, not an empty string
numeric_string: 123 # This is a number, not a string |
Document Boundaries | Use document separators for multi-document files |
---
# First configuration
environment: development
---
# Second configuration
environment: production
... |
Comments for Clarity | Use comments to explain complex structures |
# Database connection settings
database:
host: localhost
port: 5432 # Default PostgreSQL port
credentials:
# Use environment variables in production
username: ${DB_USER:-postgres}
password: ${DB_PASS:-admin} |
Anchors for Repetition | Use anchors to avoid repetition |
# Define defaults once
defaults: &defaults
timeout: 30
retries: 3
logging: true
# Reuse with overrides
service1:
<<: *defaults
name: auth-service
service2:
<<: *defaults
name: data-service
timeout: 60 # Override specific setting |
Schema Validation | Validate YAML against a schema |
# Use tools like yamllint, kwalify, or JSON Schema
# to validate your YAML files against a defined schema
# Example command:
# yamllint config.yaml
# jsonschema -i config.yaml schema.json |
Common Mistakes to Avoid
Mistake | Description | Solution |
---|
Tab Characters | Using tabs instead of spaces for indentation |
# Always use spaces (usually 2) for indentation
# Many editors can be configured to insert spaces when tab is pressed |
Inconsistent Indentation | Mixing different indentation levels |
# Ensure all indentation is consistent, typically 2 spaces
# Use an editor with YAML support and indentation guides |
Unquoted Special Characters | Leaving special characters unquoted |
# Bad - will be parsed incorrectly
special: Hello: World
# Good - quoted to handle the colon
special: "Hello: World" |
Incorrect Block Scalar Indicators | Misusing the block scalar indicators (|, >, +, -) |
# Incorrect - wrong chomping indicator
description: |+
First line.
Second line.
third_key: value # This might not work as expected
# Correct
description: |
First line.
Second line.
third_key: value |
Ambiguous Types | Relying on type inference for ambiguous values |
# Ambiguous - numeric-looking string
zip: 02138 # Will be interpreted as an integer
# Clear - explicitly quoted
zip: "02138" # Will be a string |
Boolean Confusion | Forgetting that words like 'yes', 'no', 'on', 'off' are booleans |
# Will be parsed as boolean true
status: yes
# Use quotes for string values
status: "yes" |
Missing Anchors | Referencing non-existent anchors |
# Error - referencing a non-existent anchor
settings: *base # base is not defined anywhere
# Correct
base: &base
timeout: 30
settings: *base |
Advanced Features
Feature | Description | Example |
---|
Merge Keys | Use the special <<: key to merge maps |
base: &base
name: John Doe
age: 30
user:
<<: *base
role: admin # Additional key
age: 31 # Override existing key |
Complex Keys | Use complex structures as mapping keys |
? - key1
- key2
: value
# Equivalent to:
{[key1, key2]: value} |
Explicit Typing | Use YAML tags for explicit typing |
canonical: !!str 2001-12-15
integer: !!int 3
float: !!float 3.14
boolean: !!bool true
null: !!null null
datetime: !!timestamp 2001-12-15T02:59:43.1Z |
Explicit Collections | Use explicit collection types |
# Set with unique values
set: !!set
? item1
? item2
? item1 # Duplicate, will be ignored
# Ordered map
ordered_map: !!omap
- key1: value1
- key2: value2
# Order is preserved |
Tag Prefixes | Define custom tag prefixes |
%TAG !myapp! tag:example.com,2023:app/
---
# This expands to !tag:example.com,2023:app/User
config: !myapp!User
name: John |
YAML vs JSON
Feature | YAML | JSON |
---|
Comments | Supported (# for comments) | Not supported |
Data Types |
# Rich type system
- strings
- numbers
- booleans
- null
- timestamps
- binary
- sets
- more complex types |
// Limited type system
- strings
- numbers
- booleans
- null
- arrays
- objects |
Syntax Flexibility |
# Multiple ways to represent data
# Block style
items:
- item1
- item2
# Flow style
items: [item1, item2] |
// One strict syntax
{
"items": [
"item1",
"item2"
]
} |
Anchors & References |
# DRY with anchors and aliases
base: &base
key: value
extended:
<<: *base
extra: value |
// No native support for references
// Requires repetition or custom processing |
Multiline Strings |
# Native multiline support
description: |
This is a multi-line
description that preserves
line breaks. |
// No native multiline
// Requires escape characters
{
"description": "This is a multi-line\ndescription that uses\nescape characters."
} |
Readability | Generally more human-readable | Less readable, especially for complex structures |
Parsing Complexity | More complex to parse correctly | Simpler to parse |
Conversion |
# Valid JSON is valid YAML 1.2
{"key": "value"} |
// YAML must be converted to be valid JSON |
Examples
Use Case | YAML Example |
---|
Configuration File |
# Server configuration
server:
host: localhost
port: 8080
debug: true
database:
driver: postgres
host: db.example.com
credentials:
username: admin
password: ${DB_PASSWORD} # Environment variable |
Kubernetes Manifest |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80 |
GitHub Actions Workflow |
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test |
Docker Compose |
version: '3'
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./site:/usr/share/nginx/html
depends_on:
- api
api:
build: ./api
environment:
- NODE_ENV=production
- DB_HOST=db
ports:
- "3000:3000"
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
- POSTGRES_USER=app
volumes:
postgres_data: |
Tools
Tool | Description | Usage Example |
---|
yamllint | Linter for YAML files |
# Terminal command
$ yamllint config.yaml
# Configuration file (.yamllint)
rules:
line-length: {max: 100}
indentation: {spaces: 2}
document-start: disable |
yq | Command-line YAML processor (like jq for YAML) |
# Extract a value
$ yq '.server.port' config.yaml
# Update a value
$ yq '.server.port = 8080' -i config.yaml
# Convert YAML to JSON
$ yq -o=json . config.yaml |
PyYAML | YAML parser and emitter for Python |
# Python code
import yaml
# Load YAML from file
with open('config.yaml', 'r') as file:
config = yaml.safe_load(file)
# Modify data
config['server']['port'] = 8080
# Save YAML to file
with open('config.yaml', 'w') as file:
yaml.dump(config, file, default_flow_style=False) |
js-yaml | JavaScript YAML parser and serializer |
// JavaScript code
const yaml = require('js-yaml');
const fs = require('fs');
// Load YAML from file
const config = yaml.load(fs.readFileSync('config.yaml', 'utf8'));
// Modify data
config.server.port = 8080;
// Save YAML to file
fs.writeFileSync('config.yaml', yaml.dump(config)); |
yamldiff | Compare YAML files |
# Compare two YAML files
$ yamldiff file1.yaml file2.yaml |
Online YAML Validators | Web tools to validate and format YAML |
# Popular online validators:
- YAML Lint (yamllint.com)
- Online YAML Parser (onlineyamltools.com)
- JSON to YAML converter (json2yaml.com) |
Version Differences
YAML Version | Description | Notable Changes |
---|
YAML 1.0 (2004) | Original specification |
- Initial YAML specification
- Complex and less standardized
- More permissive |
YAML 1.1 (2005) | Major revision with more consistent types |
- Added many data types (timestamps, binary, etc.)
- Octal numbers with leading 0 (e.g., 010 = 8)
- More flexible handling of Boolean values
- Support for various formats of null |
YAML 1.2 (2009) | Latest stable version, more compatible with JSON |
- JSON compatibility: all JSON is valid YAML 1.2
- Changed octal notation (0o10 instead of 010)
- Restricted Boolean values to true/false, yes/no, on/off
- Simplified specification
- Multiple document streams
- Improved Unicode support |
YAML 1.2.2 (2021) | Minor revision addressing issues |
- Clarified several aspects of the specification
- Fixed inconsistencies
- Better documentation
- Still backward compatible with YAML 1.2 |
Security Concerns
Issue | Description | Mitigation |
---|
Deserialization Attacks | Arbitrary code execution through YAML parsing |
# VULNERABLE:
yaml.load(user_input) # Full YAML, allows code execution
# SAFE:
yaml.safe_load(user_input) # Restricted YAML, safer |
Entity Expansion | XML entity expansion attack via YAML parser |
# Set limits on entity expansions in your YAML parser
# Use safest parsing mode available
# For PyYAML:
yaml.safe_load(content) |
Sensitive Data Exposure | Accidental exposure of secrets in YAML files |
# BAD: Hard-coded secrets
api_key: "1234abcd"
# BETTER: Environment variables
api_key: ${API_KEY}
# BEST: Use proper secret management
# Like HashiCorp Vault, AWS Secrets Manager, etc. |
Directory Traversal | YAML could reference files outside allowed paths |
# Restrict file operations when parsing YAML
# Ensure proper path validation
# Disable unnecessary YAML features that allow file access |
Resource Exhaustion | Crafted YAML causing excessive resource usage |
# Set size limits for YAML content
# Timeout for parsing operations
# Limit recursion depth in nested structures |
Encoding and Unicode Support
Feature | Description | Example |
---|
File Encoding | YAML files should be UTF-8 encoded |
# Specify encoding when reading/writing YAML files
# Python example:
with open('file.yaml', 'r', encoding='utf-8') as file:
data = yaml.safe_load(file)
# Node.js example:
fs.readFileSync('file.yaml', 'utf8') |
Unicode Characters | YAML fully supports Unicode in keys and values |
# Direct Unicode characters
greeting: "¡Hola, mundo!"
language: "日本語"
symbol: "∞"
# Unicode escapes in double quotes
escaped: "\u00A9 2023" # © 2023 |
BOM Handling | Byte Order Mark considerations |
# YAML spec recommends against BOM in UTF-8
# But some parsers handle it properly
# To remove BOM with Python:
with open('file.yaml', 'r', encoding='utf-8-sig') as file:
data = yaml.safe_load(file) |
Non-ASCII Identifiers | Keys and anchor names can contain Unicode |
# Unicode in keys
价格: 100 # "price" in Chinese
språk: "Norwegian" # "language" in Norwegian
# Unicode in anchors
基本: &基本 # "basic" in Chinese
name: Value
引用: *基本 # Reference to the anchor |
Environmental Variables in YAML
Approach | Description | Example |
---|
Variable Substitution | Common pattern for environment variable reference |
database:
host: ${DB_HOST:-localhost} # Use DB_HOST or default to localhost
port: ${DB_PORT:-5432}
username: ${DB_USER}
password: ${DB_PASSWORD} |
Docker Compose Style | Docker Compose specific environment syntax |
version: '3'
services:
web:
image: nginx
environment:
- NODE_ENV=production
- API_KEY=${API_KEY} # From host environment |
Template Processing | Using template engines to process YAML |
# Using envsubst (Unix command)
$ envsubst < template.yaml > config.yaml
# Template example:
api:
url: https://$API_DOMAIN
key: $API_KEY |
Library-Specific | Different libraries have different approaches |
# Python with python-dotenv + pyyaml + jinja2
import os
import yaml
from dotenv import load_dotenv
from jinja2 import Template
load_dotenv()
with open('template.yaml') as f:
template = Template(f.read())
rendered = template.render(**os.environ)
config = yaml.safe_load(rendered) |
Schema Validations
Tool/Approach | Description | Example |
---|
JSON Schema | Using JSON Schema to validate YAML structure |
# schema.json
{
"type": "object",
"required": ["name", "version"],
"properties": {
"name": { "type": "string" },
"version": { "type": "string" },
"dependencies": {
"type": "object",
"additionalProperties": { "type": "string" }
}
}
}
# Validation command
$ jsonschema -i package.yaml schema.json |
Kwalify | YAML/JSON schema validator |
# schema.yaml
type: map
mapping:
name:
type: str
required: true
version:
type: str
pattern: /^\d+\.\d+\.\d+$/
dependencies:
type: map
mapping:
=:
type: str
# Validate with kwalify
$ kwalify -f schema.yaml data.yaml |
yamllint | Linter with rule-based validation |
# .yamllint configuration
extends: default
rules:
line-length: {max: 120}
indentation: {spaces: 2}
document-start: disable
trailing-spaces: enable
# Run validation
$ yamllint config.yaml |
Custom Schema Validation | Writing custom validation logic |
# Python example with cerberus
import yaml
from cerberus import Validator
schema = {
'name': {'type': 'string', 'required': True},
'age': {'type': 'integer', 'min': 0},
'email': {'type': 'string', 'regex': r'^[^@]+@[^@]+\.[^@]+$'}
}
with open('data.yaml') as f:
data = yaml.safe_load(f)
v = Validator(schema)
if not v.validate(data):
print(v.errors) |
Technique | Description | Example |
---|
Line-by-Line Comments | Multiple single-line comments |
# This is a multi-line comment
# spanning several lines in YAML.
# Each line needs its own hash symbol.
key: value |
Comment Key | Using a dedicated key for comments |
_comment: |
This is a multi-line comment
that can span several lines.
The key name can be anything, typically prefixed
with _ to indicate it's not meant to be processed.
key: value |
Unused Anchor | Create an anchor that is never referenced |
_: &comment |
This is a multi-line comment
that can span several lines.
It uses an anchor that's never referenced.
key: value |
Comment Documents | Separating comments as their own document |
--- |
This is a comment document
containing documentation that
will be parsed but typically ignored
by most applications.
---
# Actual content
key: value |
YAML Libraries
Language/Library | Description | Example Usage |
---|
Python - PyYAML | Most popular YAML library for Python |
import yaml
# Load YAML from string
data = yaml.safe_load("""
name: John
age: 30
""")
# Save to file
with open('output.yaml', 'w') as f:
yaml.dump(data, f, default_flow_style=False) |
JavaScript - js-yaml | Popular YAML library for JavaScript/Node.js |
const yaml = require('js-yaml');
const fs = require('fs');
// Load YAML from file
const data = yaml.load(fs.readFileSync('file.yaml', 'utf8'));
// Convert to YAML string
const yamlStr = yaml.dump(data, {
lineWidth: -1,
noRefs: true
}); |
Ruby - psych | Ruby's built-in YAML parser (part of standard library) |
require 'yaml'
# Load YAML
data = YAML.load_file('file.yaml')
# Convert to YAML
yaml_string = data.to_yaml
# Save to file
File.write('output.yaml', yaml_string) |
Java - SnakeYAML | Popular YAML library for Java |
import org.yaml.snakeyaml.Yaml;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.Map;
// Load YAML
Yaml yaml = new Yaml();
Map data = yaml.load(new FileInputStream("file.yaml"));
// Save YAML
FileWriter writer = new FileWriter("output.yaml");
yaml.dump(data, writer); |
Go - gopkg.in/yaml.v3 | YAML library for Go |
package main
import (
"fmt"
"io/ioutil"
"log"
"gopkg.in/yaml.v3"
)
type Config struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Tags []string `yaml:"tags"`
}
func main() {
// Read YAML file
data, err := ioutil.ReadFile("config.yaml")
if err != nil {
log.Fatalf("error: %v", err)
}
// Parse YAML
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
log.Fatalf("error: %v", err)
}
// Create YAML
newData, err := yaml.Marshal(&config)
if err != nil {
log.Fatalf("error: %v", err)
}
// Write YAML file
err = ioutil.WriteFile("output.yaml", newData, 0644)
if err != nil {
log.Fatalf("error: %v", err)
}
} |
Flow Style vs Block Style
Style | Description | Example |
---|
Block Style | Uses indentation for structure, more readable |
# Block mapping
person:
name: John Doe
age: 30
languages:
- Python
- JavaScript
- Go
# Block sequence
fruits:
- apple
- banana
- orange |
Flow Style | More compact, JSON-like syntax |
# Flow mapping
person: {name: John Doe, age: 30, languages: [Python, JavaScript, Go]}
# Flow sequence
fruits: [apple, banana, orange] |
Mixed Styles | Combining both styles for readability and compactness |
# Block style for outer structure, flow for simple inner structures
services:
web:
ports: [80, 443]
environment: {NODE_ENV: production, DEBUG: false}
db:
ports: [5432]
volumes:
- data:/var/lib/postgresql/data |
Style Selection Considerations | When to use each style |
# Use block style for:
# - Complex, deeply nested structures
# - Better readability and maintainability
# - Most configuration files
# Use flow style for:
# - Simple, compact data
# - Single-line entries
# - Compatibility with JSON |
Folded and Chomping Modifiers
Modifier | Description | Example |
---|
Literal Block (|) | Preserves newlines; standard chomping (keep single trailing newline) |
content: |
This is a multi-line
text block.
All line breaks are preserved.
next_key: value # A single newline is preserved after the block |
Folded Block (>) | Folds newlines to spaces; standard chomping (keep single trailing newline) |
content: >
This is a multi-line
text block.
Line breaks become spaces.
Blank lines still create paragraphs.
next_key: value # A single newline is preserved after the block |
Clip Chomping (|-, >-) | Strips all trailing newlines |
content: |-
This is a multi-line
text block.
No trailing newlines are kept.
next_key: value # No blank lines between this and the block |
Keep Chomping (|+, >+) | Keeps all trailing newlines |
content: |+
This is a multi-line
text block.
All trailing newlines are kept.
next_key: value # Three blank lines are preserved |
Indentation Indicators | Specifies exact indentation to strip |
content: |2
This line has 4 spaces of indentation.
This line also has 4 spaces.
This line has 2 spaces.
# With indentation indicator of 2:
# - 2 spaces are stripped from each line
# - First two lines become indented by 2 spaces
# - Third line has no indentation |
Combined Modifiers | Combining indentation and chomping |
content: >2-
This folded text has
custom indentation set to 2
and clip chomping to remove trailing newlines.
next_key: value # No space between this and the previous block |
Boolean Pitfalls
Issue | Description | Solution |
---|
Implicit Boolean Conversion | YAML converts various strings to booleans automatically |
# These are all treated as boolean true
active: true
active: True
active: TRUE
active: yes
active: Yes
active: YES
active: on
active: On
active: ON
# These are all treated as boolean false
active: false
active: False
active: FALSE
active: no
active: No
active: NO
active: off
active: Off
active: OFF |
Unintended Boolean Conversion | Words that should be strings could be interpreted as booleans |
# PROBLEM: These are converted to boolean values
status: yes # Becomes true
answer: no # Becomes false
state: on # Becomes true
# SOLUTION: Use quotes to force string interpretation
status: "yes" # Stays as string "yes"
answer: 'no' # Stays as string "no"
state: "on" # Stays as string "on" |
Version Differences | YAML 1.1 vs 1.2 boolean handling |
# YAML 1.1 (more boolean values)
- y # true
- Y # true
- yes # true
- Yes # true
- YES # true
- n # false
- N # false
- no # false
- No # false
- NO # false
# YAML 1.2 (more restricted)
# Only these are standardized:
- true # true
- True # true
- false # false
- False # false |
Case Sensitivity | Boolean words are case-insensitive |
# All these are boolean true
enabled: true
enabled: True
enabled: TRUE
# To use case-sensitive words that look like booleans:
value: "True" # String "True"
title: 'Yes' # String "Yes" |
Boolean Validation | Validate booleans in schema validation |
# JSON Schema example
{
"properties": {
"enabled": {
"type": "boolean"
},
"status": {
"type": "string",
"enum": ["yes", "no", "maybe"]
}
}
} |