TOML

2025年8月12日

はじめに

TOML(Tom’s Obvious, Minimal Language)は、設定ファイルや構成データを記述するためのシンプルなテキストフォーマットである。人間が読み書きしやすい設計で、JSONやYAMLと比べて構文が直感的であると言えるが、テーブル周りを深堀りするとそうでもない気がする。

使い分けとしては、データとしてはJSON、INIファイルくらい簡単なものならTOML、もう少し複雑なものならYAML、となるだろうか。

TOMLの基本

TOMLはキーと値key = valueが基本である。#でコメントが書ける。いくつかのデータ型とデータ構造がある。ファイルの拡張子は.tomlである。

データ型

文字列

name = "Alice"
description = "Hello, TOML!"

ダブルクォート"で囲む。エスケープも使える。

複数行で記述したい場合は、"""を使う。改行をそのまま改行にしたい場合は次のようにする。

multiline_text = """
  This is a
  multi-line
  string in TOML"""

表記上改行したいだけで、実際には1行にしたい場合は、次のようにする。

folded_text = """
  This is a \
  folded multi-line \
  string that will be \
  converted to a single line\
  """

生の文字列として扱いたい場合は、シングルクォート'を用いる。

path = 'C:\share\nodejs'

複数行にしたい場合は'''を使う。

multiline_text = '''
This is a
multi-line
string in TOML
'''

数値

age = 30
price = 19.99

整数や浮動小数点数を直接記述する。

ブール値

is_active = true
has_error = false

trueまたはfalseで表現。

日付/時刻

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

データ構造

配列

fruits = ["apple", "banana", "cherry"]

大かっこ [] で囲み、要素をカンマ区切り。

テーブル

[person]
name = "Bob"
age = 25

[テーブル名]でブロックを定義。中身はキーと値のペア。

入れ子テーブル

[owner]
name = "Charlie"
[owner.pet]
name = "Mochi"
type = "cat"

ドット.で階層構造を表現する。これは、以下のように書いても同じである。

[owner]
name = "Charlie"
pet.name = "Mochi"
pet.type = "cat"
[owner]
name = "Charlie"
pet = { name = "Mochi", type = "cat" }

テーブルの配列

[[]]でテーブルの配列を作ることができる。

[[pets]] # 1つ目のテーブル
name = "Mochi"
type = "cat"
age = 3

[[pets]] # 2つ目のテーブル
name = "Pochi"
type = "dog"
age = 5

[[pets]] # 3つ目のテーブル
name = "Hana"
type = "rabbit"
age = 2

あえて空の要素を作りたい場合は、名前だけ書いて中身は空にすればよい。

[[pets]]
name = "Mochi"
type = "cat"
age = 3

[[pets]] # 空の要素

[[pets]]
name = "Hana"
type = "rabbit"
age = 2

実践的な使用

TOMLの検証

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

$ python -c "import tomllib; tomllib.load(open('config.toml', 'rb')); print('OK')"

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

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

# config.toml
# アプリケーション設定
[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]
[special.features]
feature1 = true
feature2 = true

[special.thresholds]
cpu = 90
memory = 80

Pythonでの利用例

# read_toml.py
import tomllib
import logging
from typing import Dict, Any

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

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

def main():
    # 設定ファイルを読み込む
    config = load_config('config.toml')
    
    # ログ設定を適用
    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 tomllib
import json
import sys

# TOMLファイルをJSONに変換
def toml_to_json(toml_file, json_file=None):
    try:
        # TOMLファイルを読み込み
        with open(toml_file, 'rb') as f:
            toml_data = tomllib.load(f)
        
        # JSONに変換
        json_data = json.dumps(toml_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"✅ {toml_file} → {json_file} に変換完了")
        else:
            # 標準出力に表示
            print(json_data)
            
    except Exception as e:
        print(f"エラー: {e}")
        sys.exit(1)

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