YAML Formatter & Validator
Format YAML, validate it, and convert between YAML and JSON — without losing comments
Clean up YAML with a CodeMirror-powered editor, validate it for syntax errors with line-and-column feedback, and convert in either direction between YAML and JSON. Comments and key order are preserved — important for Kubernetes manifests, Docker Compose files, Ansible playbooks, and GitHub Actions workflows. Includes a CI/CD template library with 25+ production-ready examples.
Input YAML
Formatted YAMLcomments preserved
Paste YAML on the left to format it here.
Related developer tools
CI/CD YAML template library
Production-shaped YAML for the platforms developers ask about. Click a template to load it into the editor — format, validate, convert to JSON, or copy as-is.
Deployment, Service, Ingress, ConfigMap, Secret, Job, CronJob, HPA — all production-shaped.
A typical Deployment with 3 replicas, resource limits, and a readiness probe.
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app
labels:
app: example
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example
image: example/api:1.4.2
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
ClusterIP Service exposing port 80 -> targetPort 8080.
apiVersion: v1
kind: Service
metadata:
name: example-svc
spec:
selector:
app: example
ports:
- name: http
port: 80
targetPort: 8080
type: ClusterIP
NGINX Ingress with TLS via cert-manager annotation.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-svc
port:
number: 80
ConfigMap with mixed key/value pairs and a multi-line config file.
apiVersion: v1
kind: ConfigMap
metadata:
name: example-config
data:
LOG_LEVEL: info
DATABASE_HOST: postgres
app.properties: |
server.port=8080
server.shutdown=graceful
logging.format=json
Secret holding base64-encoded values. Use kubectl create secret in real usage.
apiVersion: v1 kind: Secret metadata: name: example-secret type: Opaque data: DATABASE_PASSWORD: c3VwZXJzZWNyZXQ= API_TOKEN: dG9rZW4tdmFsdWU=
Single-shot Job with backoffLimit and TTL after completion.
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
spec:
backoffLimit: 3
ttlSecondsAfterFinished: 600
template:
spec:
restartPolicy: OnFailure
containers:
- name: migrate
image: example/migrate:1.4.2
command: ["./migrate", "up"]
Daily CronJob with concurrencyPolicy: Forbid.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-cleanup
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: cleanup
image: alpine:3.20
command: ["/bin/sh", "-c", "echo nightly cleanup"]
CPU-based HPA scaling between 2 and 10 replicas.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: example-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: example-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Default-deny ingress with an exception for the frontend namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-allow-frontend
spec:
podSelector:
matchLabels:
app: example
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 8080
YAML Reference
The 80% of YAML you actually use — syntax, gotchas, formatting choices, and the differences between YAML 1.1 and YAML 1.2 that trip people up.
Quick syntax overview
YAML uses indentation (always spaces — never tabs) to denote structure. The same data can be written in block form (the readable default) or flow form (JSON-like).
server:
host: example.com
port: 8080
hosts:
- 192.168.1.1
- 192.168.1.2server: { host: example.com, port: 8080, hosts: [192.168.1.1, 192.168.1.2] }YAML 1.1 vs YAML 1.2 — the gotchas
| Value | YAML 1.1 reads as | YAML 1.2 reads as | Notes |
|---|---|---|---|
| yes / no | true / false | string | The famous “Norway problem”. |
| on / off | true / false | string | Bites GitHub Actions YAML where “on:” is a real key. |
| y / Y / n / N | true / false | string | Avoid using single-letter bools entirely. |
| 012 | octal 10 | string | YAML 1.2 requires 0o prefix for octal. |
| 3:00 | number (sexagesimal) | string | Old base-60 parsing — gone in 1.2. |
Defensive fix: quote any string that looks boolean-ish ("yes", "no", "on", "off"). Our formatter uses YAML 1.2 semantics, but older Ansible (≤ 2.9) and js-yaml in “legacy” mode still use 1.1.
Multi-line strings — | vs > vs "
| (literal block)
Preserves newlines. Use for scripts, config files inside ConfigMap, multi-line text.
script: | set -e echo hello echo world
> (folded block)
Newlines fold into spaces. Use for long descriptions that should wrap.
description: > This is a very long description that will end up on one line.
|- (strip trailing newlines)
Same as | but drops the trailing newline.
|+ (keep all trailing newlines)
Same as | but preserves trailing blank lines.
Anchors and aliases
&name defines an anchor, *name references it. Common in Docker Compose (DRY ports/networks) and CircleCI configs.
defaults: &defaults
restart: unless-stopped
logging:
driver: json-file
services:
web:
<<: *defaults
image: web:latest
api:
<<: *defaults
image: api:latestOur formatter preserves anchors and aliases (some formatters expand them, which loses intent).
Gotchas worth a one-liner
- Tabs are forbidden. Always indent with spaces. Configure your editor to convert tab-to-spaces in .yaml files.
- Trailing whitespace can change how some parsers handle multi-line strings — strip it.
- Duplicate keys are valid in YAML 1.2 syntax but most parsers reject them. Our validator surfaces them as warnings.
- Document separator (
---) is required when you put multiple YAML docs in one file. Single-doc YAML doesn't need it. - Colons in unquoted strings (e.g.
message: Hello: World) cause a parse error. Quote the value. - Empty values are
null, not the empty string.x:= null;x: ""= empty string.
Frequently Asked Questions
Common questions about YAML formatting, JSON conversion, Kubernetes / Docker Compose / Ansible / GitHub Actions YAML, and YAML 1.1 vs 1.2 gotchas.