YAML Tools

Convert between YAML and JSON, validate YAML syntax, and format YAML documents

Essential for working with configuration files, Docker Compose, Kubernetes manifests, and CI/CD pipelines. YAML's human-friendly syntax makes it perfect for settings that need to be both machine-readable and easy to edit. Our tools help you convert, validate, and work with YAML files efficiently.

What is YAML?

YAML (YAML Ain't Markup Language) is a human-readable data serialization standard that was first proposed by Clark Evans in 2001, with Ingy döt Net and Oren Ben-Kiki as co-designers. Originally meaning "Yet Another Markup Language," it was renamed to emphasize its data-oriented nature rather than document markup.

History & Creation

YAML 1.0 was released in 2004, with version 1.2 arriving in 2009. It was designed to be a more readable alternative to XML and JSON, drawing inspiration from Python's indentation-based syntax, Perl's data types, and email header format (RFC 822).

Where YAML is Used

  • Docker Compose configurations
  • Kubernetes manifests and Helm charts
  • CI/CD pipelines (GitHub Actions, GitLab CI)
  • Ansible playbooks and automation
  • Application configuration files
  • API specifications (OpenAPI/Swagger)
  • Static site generators (Jekyll, Hugo)

Benefits Over Other Formats

  • vs JSON: More readable, supports comments, multi-line strings, references
  • vs XML: Less verbose, cleaner syntax, easier to write by hand
  • vs INI: Supports nested structures, lists, and complex data types
  • vs TOML: More widely supported, better for deeply nested data

Working with YAML Across Operating Systems

🪟 Windows

  • VS Code with YAML extension
  • PowerShell ConvertFrom-Yaml module
  • Python with PyYAML: pip install pyyaml
  • yq for command-line processing

🍎 macOS

  • Built-in Ruby YAML support
  • Install yq via Homebrew: brew install yq
  • Python yaml module pre-installed
  • TextMate or Sublime Text for editing

🐧 Linux

  • yamllint for validation
  • yq and jq for processing
  • Python/Ruby YAML libraries
  • vim/emacs YAML modes

Convert YAML ↔ JSON

Convert between YAML and JSON formats seamlessly

YAML Structure Examples & Best Practices

YAML's human-friendly syntax makes it ideal for configuration files and data exchange. Here are comprehensive examples demonstrating various YAML patterns and their benefits.

Basic YAML Structures

Simple Key-Value Pairs

Basic YAML structure with scalar values

# User configuration
name: John Doe
email: john.doe@example.com
age: 30
active: true
registered: 2024-01-15

# Inline format also supported
user: {name: Jane Smith, email: jane@example.com, age: 28}

Lists and Arrays

Different ways to represent lists in YAML

# Block style list
fruits:
  - apple
  - banana
  - orange

# Flow style list
vegetables: [carrot, broccoli, spinach]

# List of objects
employees:
  - name: Alice Johnson
    department: Engineering
    skills:
      - Python
      - JavaScript
      - Docker
  - name: Bob Smith
    department: Marketing
    skills: [SEO, Content Writing, Analytics]

Advanced YAML Features

Multi-line Strings

Different ways to handle multi-line text in YAML

# Literal style (preserves newlines)
description: |
  This is a multi-line
  description that preserves
  line breaks and indentation.
    This line is indented.

# Folded style (converts newlines to spaces)
summary: >
  This is a long paragraph that
  will be folded into a single
  line with spaces between.

# Chomp indicators
keep_final_newline: |+
  This keeps the final newline

strip_final_newline: |-
  This strips the final newline

Anchors and References

Reuse data with YAML anchors to avoid duplication

# Define an anchor
default_settings: &defaults
  timeout: 30
  retries: 3
  logging: true

# Reference the anchor
development:
  <<: *defaults
  debug: true
  timeout: 60  # Override specific value

production:
  <<: *defaults
  debug: false
  cache: true

# Anchor for a value
db_host: &dbhost localhost

services:
  api:
    database: *dbhost
  worker:
    database: *dbhost

Real-World Configuration Examples

Docker Compose Configuration

Multi-container Docker application setup

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
    networks:
      - frontend

  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://user:pass@db:5432/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
    networks:
      - frontend
      - backend

  db:
    image: postgres:14
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - backend

volumes:
  postgres_data:

networks:
  frontend:
  backend:

Kubernetes Deployment

Container orchestration configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: myapp:2.0
        ports:
        - containerPort: 8080
        env:
        - name: API_URL
          value: "http://api-service:3000"
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: password
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

GitHub Actions Workflow

CI/CD pipeline configuration

name: Deploy Application

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x, 16.x, 18.x]
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Deploy to production
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
      run: |
        echo "Deploying to production..."
        ./scripts/deploy.sh

Ansible Playbook

Infrastructure automation and configuration management

---
- name: Configure web servers
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    max_clients: 200
    
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: latest
        update_cache: yes
      when: ansible_os_family == "Debian"
      
    - name: Copy nginx configuration
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify:
        - restart nginx
        
    - name: Ensure nginx is running
      service:
        name: nginx
        state: started
        enabled: yes
        
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

Complex Data Structures

Application Configuration

Comprehensive app config with multiple environments

# Application configuration
app:
  name: MyApp
  version: 2.1.0
  description: >
    A comprehensive web application
    for managing customer data

# Environment-specific settings
environments:
  development:
    debug: true
    database:
      host: localhost
      port: 5432
      name: myapp_dev
      pool:
        min: 2
        max: 5
    cache:
      enabled: false
    
  production:
    debug: false
    database:
      host: db.production.example.com
      port: 5432
      name: myapp_prod
      pool:
        min: 10
        max: 50
    cache:
      enabled: true
      ttl: 3600
      redis:
        host: redis.production.example.com
        port: 6379

# Feature flags
features:
  - name: new_dashboard
    enabled: true
    rollout_percentage: 50
    excluded_users: []
    
  - name: advanced_analytics
    enabled: false
    allowed_users:
      - admin@example.com
      - beta@example.com

# API endpoints
api:
  base_url: https://api.example.com
  version: v2
  endpoints:
    users: /users
    products: /products
    orders: /orders
  rate_limiting:
    enabled: true
    requests_per_minute: 60

OpenAPI/Swagger Specification

API documentation in YAML format

openapi: 3.0.0
info:
  title: User Management API
  version: 1.0.0
  description: API for managing users
  
servers:
  - url: https://api.example.com/v1
    description: Production server
  - url: https://staging-api.example.com/v1
    description: Staging server

paths:
  /users:
    get:
      summary: List all users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  users:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                    
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserInput'
      responses:
        '201':
          description: User created
          
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time

Benefits of YAML Structures

When to Use Different YAML Features

Use Multi-line Strings For:
  • Long descriptions or documentation
  • SQL queries or scripts
  • Template content
  • Preserving formatting
Use Anchors & References For:
  • Shared configuration values
  • Default settings with overrides
  • Reducing duplication
  • Maintaining consistency

YAML vs Other Formats

Configuration Format Comparison

Same configuration in YAML vs JSON vs TOML

# YAML - Most readable for complex configs
server:
  host: localhost
  port: 8080
  ssl:
    enabled: true
    cert: /path/to/cert.pem
    key: /path/to/key.pem

# JSON equivalent - More verbose
{
  "server": {
    "host": "localhost",
    "port": 8080,
    "ssl": {
      "enabled": true,
      "cert": "/path/to/cert.pem",
      "key": "/path/to/key.pem"
    }
  }
}

# TOML equivalent - Good for simple configs
[server]
host = "localhost"
port = 8080

[server.ssl]
enabled = true
cert = "/path/to/cert.pem"
key = "/path/to/key.pem"

Common YAML Patterns

Environment Variables & Secrets

Best practices for handling sensitive data

# Never hardcode secrets
database:
  # Bad - exposed password
  # password: mysecretpassword
  
  # Good - reference environment variable
  password: ${DB_PASSWORD}
  
  # Alternative - reference from secret manager
  password: !secret database_password

# Using environment variables with defaults
app:
  port: ${PORT:-3000}
  host: ${HOST:-0.0.0.0}
  debug: ${DEBUG:-false}
  
# Reference external files
ssl:
  cert: !file /etc/ssl/certs/server.crt
  key: !file /etc/ssl/private/server.key

Conditional Configuration

Dynamic configuration based on conditions

# GitLab CI example with conditions
stages:
  - test
  - build
  - deploy

.test_template: &test_definition
  stage: test
  script:
    - npm install
    - npm test

test:unit:
  <<: *test_definition
  only:
    - merge_requests
    - main

test:integration:
  <<: *test_definition
  script:
    - npm install
    - npm run test:integration
  only:
    - main

deploy:production:
  stage: deploy
  script:
    - ./deploy.sh production
  only:
    - main
  when: manual
  environment:
    name: production
    url: https://example.com