YAML

2025年8月12日

はじめに

YAML(YAML Ain’t Markup Language)は、人間が読み書きしやすい構造化データ形式で、設定ファイルやデータ交換に広く利用されている。インデントを使ったシンプルな構文で、リストや連想配列などの複雑なデータ構造を表現できる。

YAMLの基本

YAMLの構造

YAMLはインデントで構造を表す。インデントはスペース(ふつうは2か4)で表現する。タブはNG。

parent:
  childe1: value1
  childe2: value2
    grandchilde: value3

この例ではキー-バリューの対応構造を表している。大文字小文字は区別される。

コメント

#でコメントを書ける。

# ユーザー設定
users:
  # 管理者ユーザー
  admin: true

データ型

YAMLにはいくつかのデータ型がある。型の指定は必要ない。

文字列

引用符なしでテキストを表す。

str: これは文字列

引用符を使ってもよい。エスケープがいるときは引用符が必要。

multiline: "This is a string\nthat spans\nmultiple lines"

改行したい場合は|か>を使う。

multiline_text: |
  This is a
  multi-line
  string in YAML
folded_text: >
  This is a
  folded multi-line
  string that will be
  converted to a single line

|は改行を保持するが、>は1行に変換される。

数値

整数と浮動小数点数をサポート。

int_value: 42
float_value: 3.14

ブール値

trueかfalseで値を表す。

switch: true

null値

空の値をnull、-、""で表す。

key1: null
key2: -
key3: ""

日付/時刻

date_only: 2023-10-01
datetime_with_timezone: 2023-10-01T12:30:45Z
datetime_local: 2023-10-01T12:30:45
detailed_time: 2023-10-01T12:30:45.123456+09:00

データ構造

マップ

キー-バリューの対応構造をマップ(連想配列)というが、それを次のように表す。

simple_map:
  key1: value1
  key2: value2
  key3: value3

リスト

リスト(配列)は次のように表す。

simple_list:
  - item1
  - item2
  - item3

次のように書いてもよい。

simple_list: [item1, item2, item3]

複合データ構造

マップとリストが混ざってもよい。

users:
  - name: John Doe
    age: 30
    roles:
      - admin
      - user
  - name: Jane Smith
    age: 25
    roles:
      - user

少し細かい項目

ドキュメントマーカー

ドキュメントを複数含めることができ、ドキュメントの開始を---で、終わりを...で表す。

# ドキュメント1
---
name: "Document 1"
content: "This is the first document"
...

# ドキュメント2
---
name: "Document 2"
content: "This is the second document"
...

# ドキュメント3
---
name: "Document 3"
content: "This is the third document"
...

終わりの方は省略可能。単一のドキュメントではほぼ使われないが、バリデーションでは警告が出るので、それがいやな場合は一番上に---と書けばよい。

アンカーとエイリアス

アンカーとエイリアスは、記述が重複するのを避けるための機能である。&でアンカーを設定し、*で表されるエイリアスと呼ばれるものでアンカーを参照する。

# アンカーを定義
defaults: &defaults
  adapter: postgres
  host: localhost
  port: 5432

# エイリアスで参照
development:
  <<: *defaults
  database: dev_db

test:
  <<: *defaults
  database: test_db

ここで、<<はマージキーというもので、アンカーで定義されたマップをマージする。上の例のdevelopmentは、以下の内容と同じになる。

development:
  adapter: postgres
  host: localhost
  port: 5432
  database: dev_db

実際に展開された結果が見たければ、次のようなPythonスクリプトを使えばよい。

# expand_yaml.py
import yaml

with open('your_file.yaml') as f:
    data = yaml.safe_load(f)
    print(yaml.dump(data, default_flow_style=False))

上記YAMLに対する実行結果

$ python expand_yaml.py
defaults:
  adapter: postgres
  host: localhost
  port: 5432
development:
  adapter: postgres
  database: dev_db
  host: localhost
  port: 5432
test:
  adapter: postgres
  database: test_db
  host: localhost
  port: 5432

実践的な使用

YAMLの検証

YAMLの検証を行うには、たとえばyamllintを使う。

インストール

$ pip install yamllint

実行

$ yamllint config.yaml
config.yaml
  2:1       warning  missing document start "---"  (document-start)
  11:4      error    syntax error: expected <block end>, but found '<block mapping start>' (syntax)

ディレクトリにあるすべてのファイルをチェックすることもできる。

$ yamllint .

書式のチェックだけであれば、Pythonを使って以下のようにしてもよい。

python -c "import yaml; yaml.safe_load(open('config.yaml')); print('OK')"

設定ファイルとしての利用

YAMLは設定ファイルとして利用される。

# config.yaml
# アプリケーション設定
app:
  name: "My Application"
  version: 1.0.0
  debug: true
  log_level: "INFO"

# データベース設定
database:
  host: "localhost"
  port: 5432
  name: "mydb"
  user: "admin"
  password: "secret"
  max_connections: 10

# サーバー設定
server:
  host: "0.0.0.0"
  port: 8000
  timeout: 30
  allowed_origins:
    - "http://localhost:3000"
    - "https://example.com"

# 特別な設定
special:
  features:
    - "feature1"
    - "feature2"
  thresholds:
    cpu: 90
    memory: 80

Pythonでの利用例

# read_yaml.py
import yaml
import logging
from typing import Dict, Any

def load_config(config_path: str) -> Dict[str, Any]:
    """YAML設定ファイルを読み込む"""
    with open(config_path, 'r') as file:
        config = yaml.safe_load(file)
    return config

def setup_logging(config: Dict[str, Any]) -> None:
    """ログ設定を適用"""
    log_level = config['app']['log_level']
    logging.basicConfig(
        level=log_level,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )

def main():
    # 設定ファイルを読み込む
    config = load_config('config.yaml')

    # ログ設定を適用
    setup_logging(config)

    # 設定を使用してアプリケーションを構成
    app_name = config['app']['name']
    db_config = config['database']
    server_config = config['server']

    logging.info(f"Starting {app_name} version {config['app']['version']}")

    # データベース接続(例)
    #db = connect_to_database(db_config)

    # サーバー起動(例)
    #start_server(server_config)

    # 特別な設定を使用
    if 'feature1' in config['special']['features']:
        logging.info("Feature1 is enabled")

    if config['special']['thresholds']['cpu'] > 80:
        logging.warning("High CPU threshold configured")

if __name__ == "__main__":
    main()

JSONへの変換

import yaml
import json
import sys

# YAMLファイルをJSONに変換
def yaml_to_json(yaml_file, json_file=None):
    try:
        # YAMLファイルを読み込み
        with open(yaml_file, 'r', encoding='utf-8') as f:
            yaml_data = yaml.safe_load(f)
        
        # JSONに変換
        json_data = json.dumps(yaml_data, indent=2, ensure_ascii=False)
        
        if json_file:
            # JSONファイルに出力
            with open(json_file, 'w', encoding='utf-8') as f:
                f.write(json_data)
            print(f"✅ {yaml_file} → {json_file} に変換完了")
        else:
            # 標準出力に表示
            print(json_data)
            
    except Exception as e:
        print(f"エラー: {e}")
        sys.exit(1)

# 使用例
if __name__ == "__main__":
    yaml_to_json('config.yaml', 'config.json')