YAML to JSON: Convert Online with JavaScript, Python, and CLI Tools
Convert YAML to JSON online and with code. Complete guide for JavaScript, Python, Go, and command-line YAML-to-JSON conversion.
YAML is the human-readable config format; JSON is the universal language of APIs. Convert online with DevToolBox's free tool; use js-yaml (JavaScript), PyYAML (Python), or gopkg.in/yaml.v3 (Go) in code; use yq on the command line. Watch out for YAML boolean traps (yes/no/on/off), forbidden tabs, and anchor expansion. Multi-document YAML (--- separator) converts to a JSON array.
YAML vs JSON β Key Differences
YAML (YAML Ain't Markup Language) and JSON (JavaScript Object Notation) are both data serialization formats, but with fundamentally different design philosophies. YAML is optimized for human editing with indentation-based nesting; JSON is optimized for machine parsing with strict, unambiguous syntax. The table below compares key differences in real-world use:
| Feature | YAML | JSON |
|---|---|---|
| Readability | Excellent β indentation syntax, minimal punctuation | Moderate β many quotes and brackets |
| Comments Support | Yes β lines starting with # | Not supported |
| Data Types | Strings, ints, floats, booleans, null, dates, binary | Strings, numbers, booleans, null, arrays, objects |
| File Size | Generally smaller β no quotes or braces required | Slightly larger due to required syntax characters |
| Parsing Speed | Slower β indentation-sensitive parsing | Faster β simpler grammar, widely optimized |
| Use Case | Kubernetes, Docker Compose, CI/CD, Ansible config | REST APIs, databases, machine-to-machine exchange |
Online Conversion
The fastest way to convert YAML to JSON is using an online tool. The DevToolBox YAML to JSON converter provides real-time preview, error highlighting, and formatted output β no installation required. It is ideal for one-off conversions, debugging configuration files, or verifying YAML syntax before committing to a repository.
For scenarios requiring integration into engineering workflows or automation pipelines, continue reading for language-specific code examples and command-line approaches.
JavaScript / Node.js β Using js-yaml
The js-yaml library is the most popular YAML parser in the JavaScript ecosystem, compatible with both Node.js and browser environments. The core API is yaml.load() to parse YAML into a JavaScript object, and JSON.stringify() to serialize it as JSON.
Install:
npm install js-yaml
# TypeScript types are bundled β no @types neededBasic conversion:
const yaml = require('js-yaml');
const yamlString = `
name: my-app
version: 1.0.0
database:
host: localhost
port: 5432
credentials:
user: admin
password: secret
features:
- auth
- logging
- metrics
enabled: true
`;
// Parse YAML β JavaScript object
const obj = yaml.load(yamlString);
// Serialize to JSON (pretty-printed with 2-space indent)
const json = JSON.stringify(obj, null, 2);
console.log(json);
/* Output:
{
"name": "my-app",
"version": "1.0.0",
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"user": "admin",
"password": "secret"
}
},
"features": ["auth", "logging", "metrics"],
"enabled": true
}
*/Converting a YAML file:
const yaml = require('js-yaml');
const fs = require('fs');
const path = require('path');
function yamlFileToJson(inputPath, outputPath) {
// Read YAML file
const yamlContent = fs.readFileSync(inputPath, 'utf8');
// Parse and convert
const obj = yaml.load(yamlContent);
const jsonContent = JSON.stringify(obj, null, 2);
// Write JSON file
if (outputPath) {
fs.writeFileSync(outputPath, jsonContent, 'utf8');
console.log(`Converted ${inputPath} β ${outputPath}`);
}
return jsonContent;
}
// Usage
yamlFileToJson('config.yaml', 'config.json');
yamlFileToJson('k8s-deployment.yaml', 'k8s-deployment.json');Handling multi-document YAML (--- separator):
const yaml = require('js-yaml');
const multiDocYaml = `
---
kind: Deployment
metadata:
name: api-server
---
kind: Service
metadata:
name: api-service
---
kind: ConfigMap
metadata:
name: api-config
`;
// yaml.load() only parses the FIRST document
// Use yaml.loadAll() for multi-document YAML
const documents = yaml.loadAll(multiDocYaml);
console.log(`Found ${documents.length} documents`);
// Convert the document array to JSON
const json = JSON.stringify(documents, null, 2);
console.log(json);
// Or process each document individually
documents.forEach((doc, index) => {
console.log(`Document ${index + 1}: ${doc.kind}`);
});Python β Using PyYAML
PyYAML is the standard YAML library for Python. Always use yaml.safe_load() instead of yaml.load() to prevent arbitrary code execution from untrusted YAML input β yaml.load() with untrusted data is a known security vulnerability.
Install:
pip install pyyamlBasic conversion:
import yaml
import json
yaml_string = """
server:
host: 0.0.0.0
port: 8080
timeout: 30
database:
url: postgres://localhost/mydb
pool_size: 10
ssl: true
logging:
level: info
format: json
tags:
- production
- api
- v2
"""
# Parse YAML safely (prevents code execution from untrusted YAML)
data = yaml.safe_load(yaml_string)
# Serialize to JSON with indentation
json_output = json.dumps(data, indent=2)
print(json_output)
# Output:
# {
# "server": { "host": "0.0.0.0", "port": 8080, "timeout": 30 },
# "database": { "url": "postgres://localhost/mydb", "pool_size": 10, "ssl": true },
# "logging": { "level": "info", "format": "json" },
# "tags": ["production", "api", "v2"]
# }Converting files:
import yaml
import json
import sys
from pathlib import Path
def yaml_to_json(input_path: str, output_path: str = None) -> str:
"""Convert a YAML file to JSON."""
with open(input_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
json_str = json.dumps(data, indent=2, ensure_ascii=False)
if output_path:
with open(output_path, 'w', encoding='utf-8') as f:
f.write(json_str)
print(f"Converted {input_path} β {output_path}")
return json_str
# Convert a single file
result = yaml_to_json("config.yaml", "config.json")
# Convert multiple files in a directory
for yaml_file in Path(".").glob("**/*.yaml"):
json_file = yaml_file.with_suffix(".json")
yaml_to_json(str(yaml_file), str(json_file))Multi-document YAML with yaml.safe_load_all():
import yaml
import json
multi_doc_yaml = """
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-api
spec:
replicas: 3
---
apiVersion: v1
kind: Service
metadata:
name: web-api-svc
spec:
type: ClusterIP
port: 80
"""
# yaml.safe_load() only reads the first document
# yaml.safe_load_all() returns a generator for all documents
documents = list(yaml.safe_load_all(multi_doc_yaml))
print(f"Found {len(documents)} documents")
# Serialize the entire array to JSON
print(json.dumps(documents, indent=2))Command Line Tools
Command-line conversion is ideal for shell scripts, CI/CD pipelines, and quick one-off operations. Here are the most commonly used approaches:
yq (recommended):
# Install yq (macOS)
brew install yq
# Install yq (Linux)
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
sudo chmod +x /usr/local/bin/yq
# Convert YAML file to JSON
yq -o json config.yaml
# Convert and save to file
yq -o json config.yaml > config.json
# Pretty-print with indentation
yq -o json -P config.yaml
# Convert from stdin
cat config.yaml | yq -o json
# Process specific keys during conversion
yq -o json '.database' config.yaml
# Convert multiple files
for f in *.yaml; do yq -o json "$f" > "${f%.yaml}.json"; donePython one-liner (no extra installation):
# Convert YAML stdin to JSON stdout
cat file.yaml | python3 -c "import yaml,json,sys; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))"
# Convert YAML file to JSON file
python3 -c "
import yaml, json
with open('input.yaml') as f:
data = yaml.safe_load(f)
with open('output.json', 'w') as f:
json.dump(data, f, indent=2)
"
# One-liner with file args
python3 -c "import yaml,json,sys; json.dump(yaml.safe_load(open(sys.argv[1])), open(sys.argv[2],'w'), indent=2)" input.yaml output.jsonRuby one-liner:
# Ruby one-liner (available on most Unix systems)
ruby -ryaml -rjson -e 'puts JSON.pretty_generate(YAML.safe_load(STDIN.read))' < file.yamlYAML Data Type Mapping to JSON
Understanding how YAML types map to JSON types is essential for avoiding conversion surprises. The following table shows common YAML type mappings:
| YAML Value | JSON Output | Notes |
|---|---|---|
| null, ~, (empty) | null | YAML null values |
| true, false | true, false | Booleans in YAML 1.1 and 1.2 |
| yes, no, on, off | true, false | Only in YAML 1.1 β always quote these |
| 42, -7 | 42, -7 | Integer numbers |
| 3.14, 1.0e10 | 3.14, 1.0e10 | Floating-point numbers |
| 0777 (octal) | 511 | Octal notation becomes decimal integer |
| 0xFF (hex) | 255 | Hex notation becomes decimal integer |
| "hello", 'world' | "hello", "world" | Strings (quotes optional in YAML) |
| !!binary <base64> | "<base64>" | Binary data becomes base64 string |
| &anchor, *alias | Expanded value | Anchors and aliases fully dereferenced |
| - item1 - item2 | ["item1", "item2"] | YAML sequences become JSON arrays |
| key: value | {"key": "value"} | YAML mappings become JSON objects |
YAML Anchors and Aliases
YAML anchors (&) define reusable data blocks, and aliases (*) reference them. During JSON conversion, all aliases are fully dereferenced (expanded inline) β JSON has no reference mechanism. Merge keys (<<: *base) are also expanded, with later keys overriding earlier ones.
Before conversion (YAML):
# YAML with anchors and aliases
defaults: &defaults
timeout: 30
retries: 3
log_level: info
production:
<<: *defaults # Merge: inherits timeout, retries, log_level
log_level: warning # Override: replaces log_level from defaults
replicas: 5
staging:
<<: *defaults # Merge: inherits all defaults
replicas: 1
# Simple alias (not merge key)
base_image: &img "node:20-alpine"
services:
web:
image: *img # Alias: becomes "node:20-alpine"
worker:
image: *img # Alias: also becomes "node:20-alpine"After conversion (JSON) β anchors fully expanded:
{
"defaults": { "timeout": 30, "retries": 3, "log_level": "info" },
"production": {
"timeout": 30,
"retries": 3,
"log_level": "warning",
"replicas": 5
},
"staging": {
"timeout": 30,
"retries": 3,
"log_level": "info",
"replicas": 1
},
"base_image": "node:20-alpine",
"services": {
"web": { "image": "node:20-alpine" },
"worker": { "image": "node:20-alpine" }
}
}Note: The JSON output is larger than the YAML source because every aliased value is fully duplicated. In configurations with heavy anchor reuse, this can significantly increase JSON file size.
Multi-Document YAML
YAML supports multiple documents in a single file, separated by ---. This is extremely common in Kubernetes (one YAML file containing a Deployment + Service + ConfigMap). When converting to JSON, multi-document YAML becomes a JSON array where each element is one document.
# Multi-document YAML (common in Kubernetes)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 8080JavaScript β yaml.loadAll():
const yaml = require('js-yaml');
const fs = require('fs');
const content = fs.readFileSync('k8s-manifests.yaml', 'utf8');
// yaml.load() β only parses FIRST document (wrong for multi-doc)
// yaml.loadAll() β parses ALL documents into an array
const documents = yaml.loadAll(content);
console.log(JSON.stringify(documents, null, 2));
// Result: [{ apiVersion: "apps/v1", kind: "Deployment", ... }, { apiVersion: "v1", kind: "Service", ... }]yq command line:
# yq automatically handles multi-document YAML
# Outputs as JSON array
yq -o json k8s-manifests.yaml
# Split into individual JSON files
yq -o json '.' k8s-manifests.yaml | jq -c '.[]' | while read doc; do
kind=$(echo "$doc" | jq -r '.kind')
echo "$doc" | jq . > "${kind,,}.json"
doneGo β gopkg.in/yaml.v3 + encoding/json
Go uses gopkg.in/yaml.v3 to parse YAML and the standard library encoding/json to serialize JSON. Go's strong typing makes conversion explicit and controlled. You can use interface{} for dynamic handling or define structs for type safety.
// go get gopkg.in/yaml.v3
package main
import (
"encoding/json"
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// Dynamic approach β works for any YAML structure
func yamlToJsonDynamic(yamlBytes []byte) ([]byte, error) {
// Step 1: Parse YAML into generic interface{}
var obj interface{}
if err := yaml.Unmarshal(yamlBytes, &obj); err != nil {
return nil, fmt.Errorf("yaml parse error: %w", err)
}
// Step 2: Serialize to JSON
jsonBytes, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return nil, fmt.Errorf("json marshal error: %w", err)
}
return jsonBytes, nil
}
// Struct-based approach β type-safe, best for known schemas
type Config struct {
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Server struct {
Host string `yaml:"host" json:"host"`
Port int `yaml:"port" json:"port"`
} `yaml:"server" json:"server"`
Features []string `yaml:"features" json:"features"`
}
func main() {
yamlContent := []byte(`
name: my-service
version: "2.1.0"
server:
host: 0.0.0.0
port: 8080
features:
- auth
- rate-limiting
- tracing
`)
// Dynamic approach
jsonBytes, err := yamlToJsonDynamic(yamlContent)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fmt.Println(string(jsonBytes))
// Struct-based approach
var cfg Config
if err := yaml.Unmarshal(yamlContent, &cfg); err != nil {
panic(err)
}
out, _ := json.MarshalIndent(cfg, "", " ")
fmt.Println(string(out))
}Kubernetes and CI/CD Use Cases
Converting YAML to JSON has several practical applications in DevOps workflows:
1. Interacting with the Kubernetes API:
# kubectl can apply both YAML and JSON
# Convert k8s manifest YAML to JSON for API calls
yq -o json deployment.yaml > deployment.json
# Use with curl to call the Kubernetes API directly
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
https://$K8S_API/apis/apps/v1/namespaces/default/deployments \
-d @deployment.json
# Validate manifest before applying
kubectl apply --dry-run=client -f deployment.yaml
yq -o json deployment.yaml | kubectl apply --dry-run=client -f -2. GitHub Actions workflow conversion:
# GitHub Actions step to convert YAML config to JSON for downstream tools
- name: Convert YAML config to JSON
run: |
pip install pyyaml
python3 -c "
import yaml, json
with open('config.yaml') as f:
data = yaml.safe_load(f)
with open('config.json', 'w') as f:
json.dump(data, f, indent=2)
"
echo "Config converted:"
cat config.json
# Or using yq in GitHub Actions
- name: Convert with yq
uses: mikefarah/yq@master
with:
cmd: yq -o json config.yaml > config.json3. Helm values.yaml to JSON for Terraform:
# Convert Helm values.yaml to JSON for use in Terraform helm_release
yq -o json values.yaml > values.json
# In Terraform:
# resource "helm_release" "app" {
# values = [file("values.json")]
# }
# Or generate Terraform variables from YAML config
python3 -c "
import yaml, json
with open('app-config.yaml') as f:
config = yaml.safe_load(f)
# Write as Terraform tfvars JSON
with open('terraform.tfvars.json', 'w') as f:
json.dump(config, f, indent=2)
"Common Pitfalls and Edge Cases
1. The Boolean Trap (YAML 1.1)
YAML 1.1 treats a surprisingly large set of values as booleans. This is the most common source of conversion bugs:
# YAML 1.1 boolean trap β these all become true or false in JSON!
country: NO # β false (Norway country code!)
debug: yes # β true
feature_flag: on # β true
cache: off # β false
verbose: y # β true (short form)
quiet: n # β false (short form)
# Fix: always quote ambiguous strings
country: "NO" # β "NO" (string)
debug: "yes" # β "yes" (string)
feature_flag: "on" # β "on" (string)
# YAML 1.2 only treats these as booleans:
# true, false (case-insensitive)
# All other values are strings2. Octal Numbers (0777 β 511)
# File permissions as octal numbers become decimal integers!
chmod_value: 0777 # β 511 in JSON (not "0777"!)
umask: 022 # β 22 in JSON
# Fix: quote the value to keep it as a string
chmod_value: "0777" # β "0777" (string)
umask: "022" # β "022" (string)
# Or use explicit YAML tag
chmod_value: !!str 0777 # β "0777"3. Multiline Strings (| literal vs > folded)
# Literal block (|) β preserves newlines exactly
script: |
#!/bin/bash
echo "Starting..."
npm install
npm test
# JSON: "#!/bin/bash
echo "Starting..."
npm install
npm test
"
# Folded block (>) β joins lines with spaces (like HTML)
description: >
This is a long
description that
wraps across lines.
# JSON: "This is a long description that wraps across lines.
"
# Chomping indicators control trailing newlines:
# | (default) β keeps exactly one trailing newline
# |- β strips all trailing newlines
# |+ β keeps all trailing newlines4. Tabs Are Forbidden
# WRONG: tabs cause parse errors
server:
host: localhost # β tab character β YAML parse error!
port: 8080
# CORRECT: always use spaces (2 is the convention)
server:
host: localhost # β 2 spaces
port: 8080
# Configure your editor to insert spaces (not tabs) for .yaml files
# .editorconfig:
# [*.{yaml,yml}]
# indent_style = space
# indent_size = 2Reverse: JSON to YAML
Converting JSON to YAML is equally straightforward. Every major YAML library supports this direction. Keep in mind: comments cannot survive a JSON round-trip since JSON has no comment syntax.
JavaScript (js-yaml):
const yaml = require('js-yaml');
const jsonObj = {
name: "my-app",
version: "1.0.0",
server: { host: "0.0.0.0", port: 8080 },
features: ["auth", "logging"]
};
// yaml.dump() converts JS object β YAML string
const yamlOutput = yaml.dump(jsonObj, {
indent: 2, // 2-space indentation
lineWidth: 120, // wrap at 120 chars
noRefs: true, // don't use aliases in output
});
console.log(yamlOutput);
// name: my-app
// version: 1.0.0
// server:
// host: 0.0.0.0
// port: 8080
// features:
// - auth
// - loggingPython (PyYAML):
import yaml
import json
json_string = '{"name":"my-app","server":{"host":"localhost","port":8080},"tags":["api","v2"]}'
data = json.loads(json_string)
# yaml.dump() serializes Python dict β YAML string
yaml_output = yaml.dump(data, default_flow_style=False, indent=2, allow_unicode=True)
print(yaml_output)
# name: my-app
# server:
# host: localhost
# port: 8080
# tags:
# - api
# - v2yq reverse conversion:
# Convert JSON to YAML with yq
yq -oy config.json # -o yaml (can also use --output-format=yaml)
yq -oy config.json > config.yaml
# Convert JSON stdin to YAML
echo '{"name":"app","port":3000}' | yq -oy- YAML is for human-edited config files (Kubernetes, Docker Compose, GitHub Actions); JSON is for APIs and machine-to-machine communication.
- Use DevToolBox's online tool for quick conversions; js-yaml (JavaScript), PyYAML (Python), gopkg.in/yaml.v3 (Go) for code; yq for the command line.
- Always use yaml.safe_load() in Python β yaml.load() is a known code execution vulnerability with untrusted input.
- Boolean trap: yes/no/on/off/y/n are all booleans in YAML 1.1. Always quote strings that could be misread as booleans.
- YAML anchors (&) and aliases (*) are fully expanded in JSON output β the resulting JSON may be larger than the YAML source.
- Multi-document YAML (--- separator) requires yaml.loadAll() or yaml.safe_load_all() and converts to a JSON array.
- YAML forbids tab characters for indentation β always use spaces (2 is the convention). Enforce with .editorconfig in your editor.