IS
ISSARAPONG
Developer
🇹🇭 ภาษาไทย

ทำความเข้าใจ YAML

คู่มือฉบับสมบูรณ์เกี่ยวกับ YAML (YAML Ain't Markup Language) — โครงสร้าง ชนิดข้อมูล การใช้งานใน Python, JavaScript, Go และแนวทางปฏิบัติที่ดีสำหรับนักพัฒนา

Issarapong15 มิถุนายน 25675 นาที

ทำความเข้าใจ YAML

YAML (YAML Ain't Markup Language) คือรูปแบบการจัดเก็บข้อมูลที่ออกแบบมาให้อ่านง่ายสำหรับมนุษย์ ใช้อย่างแพร่หลายในไฟล์ Config, CI/CD pipelines, Infrastructure as Code และ Kubernetes manifests

YAML คืออะไร?

YAML เป็น Superset ของ JSON หมายความว่าไฟล์ JSON ทุกไฟล์ถือเป็น YAML ที่ถูกต้องด้วย แต่ YAML มี syntax ที่กระชับและอ่านง่ายกว่า เหมาะสำหรับไฟล์ที่มนุษย์ต้องแก้ไขบ่อย

เหตุผลที่ YAML ได้รับความนิยม

  • อ่านง่าย — ไม่มีวงเล็บหรือ quote มากเกินไป
  • รองรับ Comment — ใส่ # เพื่อเขียน comment ได้
  • ยืดหยุ่น — รองรับ multiline string และโครงสร้างซับซ้อน
  • มาตรฐาน DevOps — ใช้ใน Docker Compose, Kubernetes, Ansible, GitHub Actions

โครงสร้างและชนิดข้อมูล

YAML ใช้ การย่อหน้า (indentation) ด้วย space (ไม่ใช่ tab) เพื่อแสดงโครงสร้าง

ชนิดข้อมูลพื้นฐาน

# String
name: "Alice"
message: Hello World   # ไม่ต้องใส่ quote ก็ได้

# Number
age: 30
price: 9.99
negative: -5

# Boolean
isActive: true
isDeleted: false

# Null
address: null
nickname: ~          # ~ ก็หมายถึง null

# Date
createdAt: 2024-06-15

Object (Mapping)

user:
  name: Alice
  email: [email protected]
  age: 25
  profile:
    avatar: https://example.com/avatar.png
    bio: "นักพัฒนาซอฟต์แวร์"

Array (Sequence)

# Block style
fruits:
  - apple
  - banana
  - cherry

# Flow style (เหมือน JSON)
fruits: [apple, banana, cherry]

# Array of objects
users:
  - name: Alice
    age: 25
  - name: Bob
    age: 30

Multiline String

# Literal block (|) — เก็บ newline ไว้
description: |
  บรรทัดแรก
  บรรทัดสอง
  บรรทัดสาม

# Folded block (>) — แปลง newline เป็น space
summary: >
  บรรทัดนี้จะถูก
  รวมเป็นบรรทัดเดียว
  โดยอัตโนมัติ

ตัวอย่างการใช้งานจริง

Docker Compose

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: your_secure_password_here
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

GitHub Actions

# .github/workflows/ci.yml
name: CI Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

Kubernetes Deployment

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app:1.0
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: production

การใช้งานใน Python

import yaml

# อ่านไฟล์ YAML
with open("config.yaml", "r", encoding="utf-8") as f:
    config = yaml.safe_load(f)

print(config["database"]["host"])

# เขียนไฟล์ YAML
data = {
    "app": "my-service",
    "version": "1.0.0",
    "features": ["auth", "api", "dashboard"]
}

with open("output.yaml", "w", encoding="utf-8") as f:
    yaml.dump(data, f, allow_unicode=True, default_flow_style=False)

# Parse YAML string
yaml_string = """
name: Alice
tags:
  - python
  - developer
"""
parsed = yaml.safe_load(yaml_string)
print(parsed["name"])  # Alice

หมายเหตุ: ใช้ yaml.safe_load() เสมอ (ไม่ใช่ yaml.load()) เพื่อป้องกันช่องโหว่ด้านความปลอดภัย

การใช้งานใน JavaScript/Node.js

import { parse, stringify } from 'yaml'; // หรือใช้ js-yaml

// Parse YAML string
const yamlString = `
name: Alice
age: 25
tags:
  - developer
  - designer
`;

const data = parse(yamlString);
console.log(data.name); // Alice
console.log(data.tags); // ['developer', 'designer']

// แปลง object เป็น YAML string
const obj = { name: 'Bob', active: true, scores: [10, 20, 30] };
const yaml = stringify(obj);
console.log(yaml);
// name: Bob
// active: true
// scores:
//   - 10
//   - 20
//   - 30

การใช้งานใน Go

package main

import (
    "fmt"
    "gopkg.in/yaml.v3"
)

type Config struct {
    Name     string   `yaml:"name"`
    Port     int      `yaml:"port"`
    Features []string `yaml:"features"`
}

func main() {
    // Parse YAML
    yamlStr := `
name: my-app
port: 8080
features:
  - auth
  - logging
`
    var config Config
    yaml.Unmarshal([]byte(yamlStr), &config)
    fmt.Println(config.Name)  // my-app
    fmt.Println(config.Port)  // 8080

    // Marshal to YAML
    out, _ := yaml.Marshal(config)
    fmt.Println(string(out))
}

YAML Anchors และ Aliases

Anchors (&) และ Aliases (*) ช่วยลดการเขียนซ้ำ

# กำหนด anchor
defaults: &defaults
  timeout: 30
  retries: 3
  logLevel: info

# ใช้ alias
production:
  <<: *defaults    # Merge key — รับค่าจาก defaults
  logLevel: warn   # Override เฉพาะที่ต้องการ

staging:
  <<: *defaults
  timeout: 60

กฎที่ควรระวัง

Indentation ต้องใช้ Space ไม่ใช่ Tab

# ✅ ถูกต้อง (space)
parent:
  child: value

# ❌ ผิด (tab)
parent:
	child: value

String ที่มีอักขระพิเศษต้องใส่ Quote

# ✅ ใส่ quote ป้องกันการตีความผิด
version: "1.0"         # ไม่ใส่จะกลายเป็น number
active: "true"         # ไม่ใส่จะกลายเป็น boolean
colon: "key: value"    # มี : ต้องใส่ quote

ตัวเลขพิเศษ

# ค่าเหล่านี้ถูก parse เป็นชนิดที่ไม่ใช่ string
infinity: .inf
not-a-number: .nan
octal: 0o17           # 15 ในฐาน 8
hex: 0xFF             # 255 ในฐาน 16

เปรียบเทียบ YAML กับ JSON

# YAML — อ่านง่ายกว่า รองรับ comment
name: Alice       # ชื่อผู้ใช้
age: 25
tags:
  - developer
  - designer
// JSON — เหมาะกับ API และการส่งข้อมูล
{
  "name": "Alice",
  "age": 25,
  "tags": ["developer", "designer"]
}
คุณสมบัติYAMLJSON
Comment✅ รองรับ❌ ไม่รองรับ
Multiline string✅ ง่าย❌ ต้องใช้ \n
การอ่าน✅ ง่ายกว่าปานกลาง
Parse ง่ายปานกลาง✅ ง่ายกว่า
ใช้กับ API❌ ไม่นิยม✅ มาตรฐาน
ใช้กับ Config✅ มาตรฐานปานกลาง

แนวทางปฏิบัติที่ดี

  • ใช้ 2 spaces สำหรับการย่อหน้า (มาตรฐานที่นิยมที่สุด)
  • ใส่ quote string ที่คลุมเครือ — โดยเฉพาะ true, false, null, yes, no
  • ตรวจสอบด้วย linter — ใช้ yamllint เพื่อหาข้อผิดพลาด
  • ระวัง trailing space — อาจทำให้ parse ผิดพลาด
  • ใช้ safe_load ใน Python — ไม่ใช้ load() เพื่อความปลอดภัย

เครื่องมือที่เกี่ยวข้อง

  • JWT Decoder — JWT ใช้ JSON ซึ่งเป็น Subset ของ YAML
  • Base64 Encoder — ข้อมูลใน YAML มักถูก Base64 encode
  • URL Encoder/Decoder — เข้ารหัสข้อมูลสำหรับใช้ใน URL