Skip to content
Back to Blog
informational

TOMLとは?YAMLを凌駕した設定言語

2026-05-17 9 min read

TOMLの正体

TOMLは「Tom's Obvious, Minimal Language」の略です。その生みの親であるGitHub共同創設者のトム・プレストン=ワーナーは、2013年当時、既存の設定フォーマットにうんざりしていました。この言語は、2021年1月に最初の安定版リリースであるTOML v1.0.0が登場するまで、約8年間も成熟期間を経てきました。この長い洗練期間は、その設計がいかに真剣に検討されたかを物語っています。 TOMLの核心は、設定ファイル形式であるという点です。JSONのような汎用的なデータシリアル化形式でもなければ、マークアップ言語でもありません。その目的は、人間にとって読み書きが容易でありながら、ハッシュテーブル(または選択した言語で辞書、マップ、オブジェクトなどと呼ばれるもの)に明確にマッピングされることです。 ごくシンプルなTOMLファイルは非常に簡単です。 ``` title = "My Application" version = "2.4.1" debug = false [database] host = "localhost" port = 5432 max_connections = 100 ``` すべての値には明示的な型があります。`"localhost"`は文字列です。`5432`は整数です。`false`はブーリアンであり、文字列の`"false"`でも、`0`でも、`null`でもありません。この厳密さこそがTOMLの全てであり、開発者がTOMLを選ぶ主な理由です。特定のYAMLライブラリの癖のせいで、ポート番号が文字列として解析されるのか、それとも整数として解析されるのか、などと悩んで時間を無駄にすることは決してありません。

なぜYAMLは解決すべき問題となったのか

YAMLは人間にとって扱いやすいという点で高く評価されています。小さなファイルであれば、それは真実です。しかし、設定が大きくなるにつれてその親しみやすさは急速に失われ、設計上の選択が問題を引き起こし始めます。 最も悪名高い例は「ノルウェー問題」です。YAML 1.1(多くのパーサーでは今でもデフォルトです)では、2文字の国コード`NO`がブーリアン値の`false`として解析されます。`country: NO`のような設定は、サイレントにデータを破損させてしまうのです。これは、`yes`、`no`、`on`、`off`、`true`、`false`など、さまざまな大文字・小文字の組み合わせにも当てはまります。YAML 1.2でこの問題は修正されましたが、ツールがどのパーサーバージョンを使っているかを常に制御できるわけではありません。 それから、重要なホワイトスペースの問題もあります。YAMLはインデントを使って構造を定義するため、たった1つのスペースの配置ミスが、ファイル全体の意味をサイレントに変更したり、完全に壊したりすることがあります。CI/CDパイプラインのデバッグに1時間も費やし、結局2スペースと4スペースの不整合が原因だったと気づいた人なら、この苦痛をよく知っているはずです。 YAMLはまた、同じことを書く方法が多すぎます。スカラーはプレーン、シングルクォート、ダブルクォート、またはブロックスタイルで書けます。シーケンスはフロースタイルまたはブロックスタイルで書けます。この柔軟性は魅力的に聞こえますが、結果として、2人の開発者が同じ論理的な設定を全く異なる方法で記述することになり、差分を読みづらくし、コードレビューの効果を低下させてしまいます。 だからといってYAMLが役に立たないわけではありません。KubernetesのマニフェストやGitHub Actionsのワークフローの標準であるのには理由があります。しかし、正確性と予測可能性が何よりも重要なアプリケーション設定においては、これらの癖は深刻な負債となります。

TOMLはいかに可読性の問題を解決するか

TOMLの哲学はシンプルです。何かを記述する方法は、ただ一つ、明白な方法であるべきだというものです。制限的に聞こえるかもしれませんが、その結果、誰が書いたか、どのプロジェクトに属するかに関わらず、見た目も使い心地も同じ設定ファイルが生まれます。 TOMLは6つのスカラー型を提供します。文字列、整数、浮動小数点数、ブーリアン、オフセット日時、ローカル日付です。TOMLがRFC 3339形式の日付と時刻をファーストクラスでサポートしているのは、まさにキラー機能です。`created_at = 2024-03-15T09:30:00Z`と書けば、自分で解析する必要のある文字列ではなく、適切な日時オブジェクトになることを信頼できます。YAMLも日付を表現できますが、その動作はパーサーによって一貫性がありません。 構造はテーブル(セクション)とテーブルの配列で定義されます。テーブルには角括弧でヘッダーが付きます。`[server]`。テーブルの配列には二重の角括弧を使います。`[[products]]`。この構文は明確で、見つけやすいです。 以下は、Rustの`Cargo.toml`ファイルからの実例で、依存関係がどのように定義されているかを示しています。 ``` [dependencies] serde = { version = "1.0", features = ["derive"] } tokio = { version = "1", features = ["full"] } reqwest = "0.12" ``` 波括弧で囲まれたインラインテーブル構文は、シンプルでコンパクトな定義に最適です。より複雑なネストされたデータには、完全なテーブルヘッダーを使用します。この言語は、それぞれのスタイルをいつ使用すべきかについて明確なルールを提供しています。 コメントでさえ、親しみやすさを考慮して設計されています。Pythonやシェルスクリプトと同じように、`#`文字を使用します。ほとんどの開発者は、仕様書を一行も読まずにこの構文を知っているでしょう。

TOMLが成功した場所:実際の導入数

Rustのエコシステムは、TOML最大の成功事例です。RustのパッケージマネージャーであるCargoは、マニフェストにTOMLを義務付けています。2025年初頭の時点でcrates.ioには15万以上のパッケージがあり、そのすべてが`Cargo.toml`ファイルを持っています。これは、ごく少数のフォーマットしか通過できない、大規模な実世界のストレステストです。 PythonでのPEP 518(2016年)およびPEP 621(2021年)による採用は、`pyproject.toml`をプロジェクトのメタデータとビルド設定のための唯一の真の場所として確立しました。Poetry、Hatch、Flit、PDMといったツールはすべてこれを使用しています。リンターの設定は`[tool.ruff]`に、テストの設定は`[tool.pytest.ini_options]`に入ります。これにより、すべての設定を支配する一つのファイルと一つのフォーマットが手に入ります。 人気のある静的サイトジェネレーターであるHugoは、YAMLやJSONから移行し、TOMLをデフォルトの設定フォーマットにしました。チームは特に、TOMLの明示性と型強制における予期せぬ挙動の少なさを動機として挙げました。 言語がパーサーを標準ライブラリに追加するとき、そのフォーマットが定着したことがわかります。Pythonはまさにそれを実行し、バージョン3.11(2022年10月リリース)で`tomllib`を追加しました。これにより、外部依存なしで、どんな最新のPythonインストールでもTOMLファイルを解析できるようになりました。 また、PythonとRustだけの話ではありません。Go、.NET、JavaScriptにも、成熟した、適切にメンテナンスされたTOMLライブラリがあります。例えば、npmの`@iarna/toml`パッケージは、週に数百万回ダウンロードされています。TOMLは公式に主流になったと言えるでしょう。

TOMLの真の限界

完璧なツールは存在せず、TOMLも例外ではありません。いつ他のものに手を伸ばすべきかを知るために、その限界について正直になることが重要です。 深くネストされたデータは、TOMLのアキレス腱です。2、3レベル以上のネストが必要な場合、構文が苦痛になります。`[servers.production.database.replica]`のような長いドット区切りのキーを書くことになるでしょう。これは有効ですが、可読性はありません。JSONやYAMLでさえ、一般的なデータ表現のために構築されているため、この点では単純に優れています。 複雑なオブジェクトの大きな配列も弱点です。テーブルの配列を示す`[[products]]`構文は、すべての項目に対してそのヘッダーを繰り返す必要があります。50個の製品のリストは、50個の別々の`[[products]]`ヘッダーになります。その時点では、設定ファイルを記述しているのではなく、間違ったツールを使用していることになります。JSONやデータベースを使用すべきです。 TOMLには、YAMLが`&anchor`と`*alias`で提供するアンカーとエイリアスのサポートがありません。これは、設定のブロックを一度定義して、ファイル全体で再利用できないことを意味します。設定を繰り返す必要がある場合、2つの選択肢があります。直接複製するか、アプリケーションコードにマージロジックを組み込むかです。DRYを維持する組み込みの方法はありません。 最後に、TOMLファイルをストリームすることはできません。JSON Linesとは異なり、TOMLドキュメントは、いずれかの値にアクセスする前に、全体を読み込んで解析する必要があります。これは巨大な設定ファイルにとっては問題となる可能性がありますが、これほど大きな設定ファイルは、より深い設計上の問題の症状であることも少なくありません。 これらの制限は、TOMLが意図された目的、つまり中程度の複雑さのアプリケーション設定にとって悪い選択であることを意味しません。これらは単にTOMLの境界を定義しているだけです。

TOMLと他のフォーマット間の変換

プロジェクトをYAMLから移行している場合や、ツール間で設定データを変換する必要がある場合は、いくつかの選択肢があります。 Pythonでプログラム的に変換するには、`tomllib`(読み込み)と`tomli-w`(書き込み)ライブラリを`PyYAML`のようなYAMLパーサーと組み合わせることができます。YAMLファイルを`yaml.safe_load()`でPython辞書に読み込み、`tomli_w.dumps()`で書き出す方法は機能しますが、フラットまたは中程度にネストされたファイルに最適です。深くネストされた構造、YAMLアンカー、または複数のドキュメントを含むファイルでは、手動でのクリーンアップが必要になります。 JSONからTOMLへの変換は、両方のフォーマットが明示的な型を持つため、はるかにクリーンなマッピングが可能です。JSONの整数はTOMLの整数になり、JSONのブーリアンはTOMLのブーリアンになります。主な構造的な変更は、JSONのオブジェクトの配列をTOMLのテーブルの配列(`[[table]]`)にすることですが、これは優れたコンバーターが処理できます。 CocoConvertのようなオンラインツールも変換を処理できます。JSONまたはYAMLファイルをアップロードし、出力フォーマットとしてTOMLを選択すれば、コンバーターが作業を行います。これは、単純な設定ファイルには最適なオプションです。アンカーや深くネストされた構造など、YAML固有の機能を持つファイルの場合、出力はまだレビューする必要があります。CocoConvertは、TOMLにきれいにマッピングできないものを見つけると変換警告を出しますが、データ構造をリファクタリングすることはできません。それはあなたが下すべき決定です。 40個のYAMLファイルからなるリポジトリ全体を変換するような一括移行では、ファイルを一つずつアップロードするのは現実的ではありません。CocoConvert APIはこれのために構築されており、リクエストをバッチ処理し、プロセス全体を自動化できます。

プロジェクトをTOMLに切り替えるべきか?

では、切り替えるべきでしょうか?その答えは、あなたのプロジェクトと、そのツールチェーンが何を期待しているかによって異なります。 2025年に新しいPythonプロジェクトを始めるのであれば、答えは断固としてイエスです。`pyproject.toml`を使いましょう。エコシステムはこれに標準化されており、これに逆らうのは無駄な摩擦を生むだけです。プロジェクトのメイン設定ファイルで`[tool.ruff]`セクションを使うのが標準なのに、別の`ruff.toml`を作成するような人にならないでくださいね。 Rustプロジェクトを書いているのであれば、これはもはや問いですらありません。CargoはTOMLを使用しており、それはバグではなく機能です。このフォーマットの一貫性は、Rustのツールがこれほどまでにまとまりがあると感じられる大きな理由の一つです。 既存のプロジェクトでYAML設定が機能している場合、そのYAMLが痛みの元になっている場合にのみ移行することを勧めます。`config.yaml`が安定しており、チームがそれを理解しているなら、ドキュメント、スクリプト、そして人々の習慣を更新する切り替えのコストは、TOMLを使用する「純粋さ」に見合うものではないでしょう。 KubernetesやCI/CD(GitHub Actions、GitLab CIなど)の世界では、YAMLが王様です。選択肢はなく、TOMLはその分野で王座を奪おうとしているわけではありません。 本当のリトマス試験紙はこれです。YAMLファイルに、ある値が*あるべき*データ型を説明するためにコメントを書いていますか?数値が文字列として読み取られることによって引き起こされるバグを追いかけていますか?それがあなたのシグナルです。あなたはYAMLの曖昧さから卒業したのです。TOMLは、まさにこの種の問題を、最初から型を明示的にすることで解決するために設計されたのですから。