アプリケーションの設定ファイルやCI/CDのパイプライン定義、パッケージマネージャの設定など、エンジニアは日常的にさまざまなデータ形式を扱っています。YAML、JSON、TOMLはその中でも代表的なフォーマットですが、それぞれの特徴や適した用途を理解したうえで使い分けている方は意外と少ないのではないでしょうか。
本記事では、YAML・JSON・TOMLの3つのデータ形式について、構文の違い、メリット・デメリット、実際のプロジェクトでの使い分け方を具体例とともに詳しく解説します。
3つのデータ形式の概要と歴史
まずは、各フォーマットの生い立ちと基本的な特徴を把握しましょう。
JSON(JavaScript Object Notation)
JSONは2001年にDouglas Crockfordによって策定されたデータ交換フォーマットです。名前にJavaScriptとありますが、言語非依存のフォーマットとして広く利用されています。
最大の特徴は、そのシンプルさです。データ型は文字列、数値、ブーリアン、null、配列、オブジェクトの6種類のみで、仕様が非常にコンパクトです。WebAPIのレスポンス形式としてデファクトスタンダードになっており、ほぼすべてのプログラミング言語にパーサーが用意されています。
YAML(YAML Ain't Markup Language)
YAMLは2001年にClark Evans、Ingy döt Net、Oren Ben-Kiviによって開発されました。「人間にとっての可読性」を重視して設計されており、インデントベースの構文が特徴です。
JSONのスーパーセットであり、有効なJSONはすべて有効なYAMLとして解釈できます。Docker Compose、Kubernetes、GitHub Actions、Ansible など、インフラやCI/CD関連のツールで広く採用されています。
TOML(Tom's Obvious, Minimal Language)
TOMLは2013年にGitHubの共同設立者であるTom Preston-Wernerによって開発されました。「明快でミニマルな設定ファイル形式」を目指しており、INIファイルの発展形とも言える構文を持っています。
Rustのパッケージマネージャ(Cargo)の設定ファイルCargo.tomlや、Pythonのプロジェクト設定pyproject.toml、Hugoの設定ファイルなどで採用されています。
構文の比較:同じデータを3形式で表現する
同じデータ構造を3つの形式で記述し、構文の違いを比較しましょう。
JSONの記述例
{
"server": {
"host": "localhost",
"port": 8080,
"debug": true
},
"database": {
"host": "db.example.com",
"port": 5432,
"name": "myapp",
"credentials": {
"username": "admin",
"password": "secret"
}
},
"features": ["auth", "logging", "cache"],
"limits": {
"max_connections": 100,
"timeout_seconds": 30
}
}
JSONの特徴として、すべてのキーをダブルクォーテーションで囲む必要があること、末尾のカンマ(トレイリングカンマ)が許可されないこと、コメントが書けないことが挙げられます。
YAMLの記述例
# サーバー設定
server:
host: localhost
port: 8080
debug: true
# データベース設定
database:
host: db.example.com
port: 5432
name: myapp
credentials:
username: admin
password: secret
# 有効な機能
features:
- auth
- logging
- cache
# 制限値
limits:
max_connections: 100
timeout_seconds: 30
YAMLでは、インデント(通常スペース2つ)で階層構造を表現します。クォーテーションは省略可能な場合が多く、コメントも#で記述できます。ブラケットやカンマが不要なため、見た目がすっきりしています。
TOMLの記述例
# サーバー設定
[server]
host = "localhost"
port = 8080
debug = true
# データベース設定
[database]
host = "db.example.com"
port = 5432
name = "myapp"
[database.credentials]
username = "admin"
password = "secret"
# 有効な機能
features = ["auth", "logging", "cache"]
# 制限値
[limits]
max_connections = 100
timeout_seconds = 30
TOMLでは、セクション([section_name])で構造を分割し、key = value形式で値を設定します。INIファイルに慣れている方にとっては、直感的に理解できる構文です。
メリット・デメリットの詳細比較
各フォーマットの長所と短所を整理します。
JSONのメリット・デメリット
メリット
普遍的なサポート:すべてのプログラミング言語に標準またはデファクトのパーサーが存在し、データの受け渡しが容易です。
厳密な仕様:仕様が非常にシンプルで曖昧さがないため、パーサー間の互換性問題が起きにくいです。
API通信の標準:REST APIやGraphQLのレスポンス形式としてデファクトスタンダードであり、WebフロントエンドからバックエンドまでJSON一本でデータをやり取りできます。
デメリット
コメントが書けない:標準のJSONにはコメント機能がありません。設定ファイルとして使う場合、各設定項目の説明を書けないのは大きな欠点です。JSON5やJSONCなどの拡張はありますが、標準ではありません。
冗長な記法:キーのクォーテーションや構造を示す括弧により、ファイルサイズが大きくなりがちです。手作業での編集時にカンマの付け忘れなどのミスも起きやすいです。
データ型が限定的:日付型がないため、日付を文字列として表現する必要があります。
YAMLのメリット・デメリット
メリット
高い可読性:インデントベースの構文で、人間が読みやすい形式です。コメントも書けるため、設定の意図を明確に残せます。
表現力の豊かさ:アンカー(&)とエイリアス(*)によるデータの再利用、複数ドキュメントの結合、複雑なデータ構造の表現など、高度な機能を持っています。
広いエコシステム:Kubernetes、Docker Compose、GitHub Actions、Ansible、CI/CDツールなど、インフラ・DevOps系のツールで広く採用されています。
デメリット
インデントの罠:タブ文字が使えず、スペースでインデントを揃える必要があります。インデントのズレが意味の変化やパースエラーを引き起こすため、特に大きなファイルでの編集には注意が必要です。
暗黙の型変換:yes/noがブーリアンに、1.0が浮動小数点に自動変換されるなど、意図しない型変換が起きることがあります。ノルウェーの国コードNOがfalseと解釈される問題は有名です。
仕様の複雑さ:YAML 1.2の仕様は非常に大きく、パーサーの実装によって挙動が異なる場合があります。
TOMLのメリット・デメリット
メリット
明確で簡潔:YAMLのような暗黙の型変換がなく、構文が明快です。INIファイルの親しみやすさと、JSONの正確さを兼ね備えています。
コメントが書ける:JSONと違い、#でコメントを記述できます。
日付型のネイティブサポート:日時、日付、時刻の型が標準でサポートされています。
デメリット
深いネストが冗長:セクション名でネストを表現するため、3階層以上の深いネストでは[a.b.c.d]のように長くなり、可読性が下がります。
エコシステムが限定的:YAMLやJSONに比べると、採用しているツールやライブラリがまだ少ないです。
配列テーブルの記法:オブジェクトの配列を表す[[array_of_tables]]記法は、初見では理解しにくい場合があります。
用途別の使い分けガイド
フォーマットの特性を踏まえて、具体的なユースケースごとに最適な選択を解説します。
API通信・データ交換にはJSON
プログラム間のデータ交換には、JSONが最適です。以下の場面ではJSONを選びましょう。
REST API / GraphAPIのレスポンス:クライアントとサーバー間のデータ通信はJSONが標準です。
ブラウザとのデータやり取り:JavaScriptのネイティブオブジェクトとして扱えるため、フロントエンド開発では必然的にJSONを使います。
設定ファイル(コメント不要の場合):package.jsonやtsconfig.jsonのように、ツールチェーンがJSONを要求する場合はもちろんJSONを使います。
インフラ・CI/CD設定にはYAML
複雑な構成定義や人間が頻繁に編集するファイルには、YAMLが適しています。
Kubernetesマニフェスト:Podやサービスの定義など、Kubernetesの設定はYAMLが標準です。
CI/CDパイプライン:GitHub Actions、GitLab CI、CircleCIなどのワークフロー定義はYAMLで記述します。
Docker Compose:複数コンテナのオーケストレーション定義にYAMLが使われます。
Ansible Playbook:インフラのプロビジョニングや構成管理にYAMLが採用されています。
# GitHub Actionsの例
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
アプリケーション設定にはTOML
アプリケーション固有の設定ファイルには、TOMLの簡潔さが活きます。
Rustプロジェクト:Cargo.tomlでパッケージ情報や依存関係を管理します。
Pythonプロジェクト:pyproject.tomlがPythonプロジェクトの標準設定ファイルになりつつあります。
静的サイトジェネレーター:Hugoのhugo.tomlなど、サイト設定にTOMLが使われます。
# Cargo.tomlの例
[package]
name = "my-app"
version = "1.0.0"
edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
よくあるトラブルと対処法
各フォーマットで遭遇しやすい問題と、その解決方法を紹介します。
YAMLのインデントエラー
YAMLで最も頻繁に起きるのがインデントに関するエラーです。
タブとスペースの混在:YAMLではタブ文字が使えません。エディタの設定で「タブをスペースに変換」を有効にしましょう。VS Codeでは、ステータスバーの「Spaces: 2」をクリックして設定できます。
インデント幅の不一致:ファイル内でスペース2つとスペース4つが混在すると、予期しない構造解釈が起きます。.editorconfigでプロジェクト全体のインデント幅を統一しましょう。
# .editorconfig
[*.yml]
indent_style = space
indent_size = 2
[*.yaml]
indent_style = space
indent_size = 2
YAMLの型変換トラブル
YAMLの暗黙の型変換は、予期しないバグの原因になります。
# 問題のある例
country_code: NO # false として解釈される
version: 1.0 # 浮動小数点数として解釈される
port: 0800 # 8進数として解釈される場合がある
# 安全な記述
country_code: "NO" # 文字列として明示
version: "1.0" # 文字列として明示
port: "0800" # 文字列として明示
曖昧さを避けるため、文字列として扱いたい値は常にクォーテーションで囲むことをおすすめします。特にバージョン番号、電話番号、郵便番号などの「数字だが文字列として扱いたい値」には注意が必要です。
JSONのカンマ忘れ・余計なカンマ
JSONでは、末尾のカンマ(トレイリングカンマ)が許可されていません。
// エラーになる例
{
"name": "example",
"version": "1.0", // ← 最後のカンマがエラーの原因
}
// 正しい例
{
"name": "example",
"version": "1.0"
}
対策としては、VS Codeの拡張機能やJSONリンターを導入し、保存時に自動チェックを行うのが効果的です。また、tsconfig.jsonのようにJSONに準拠しつつコメントやトレイリングカンマを許容するJSONC形式をサポートするツールも増えています。
バリデーションとスキーマの活用
設定ファイルの品質を保つために、スキーマを活用したバリデーションが重要です。
JSON Schema
JSON Schemaは、JSONデータの構造を定義するための標準仕様です。必須フィールド、データ型、値の範囲などを指定でき、設定ファイルの妥当性を自動検証できます。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["server", "database"],
"properties": {
"server": {
"type": "object",
"required": ["host", "port"],
"properties": {
"host": { "type": "string" },
"port": { "type": "integer", "minimum": 1, "maximum": 65535 }
}
}
}
}
VS Codeでは、JSON Schemaを設定するだけで入力補完やバリデーションが自動的に有効になります。
YAML向けのバリデーション
YAMLファイルに対してもJSON Schemaを適用できます。VS Codeの「YAML」拡張機能(Red Hat提供)では、ファイル先頭にスキーマ指定を追加するだけでバリデーションが有効になります。
# yaml-language-server: $schema=./config-schema.json
server:
host: localhost
port: 8080
Kubernetes、Docker Compose、GitHub Actionsなどの主要なYAML設定ファイルには、SchemaStoreに公開されたスキーマが自動で適用されるため、特別な設定なしで入力補完とバリデーションを利用できます。
リントツールの導入
yamllint:YAML専用のリンターで、インデントの一貫性、行の長さ、重複キーなどをチェックします。CI/CDパイプラインに組み込むことで、設定ファイルの品質を自動的に担保できます。
jsonlint:JSON専用のバリデーターで、構文エラーを検出します。
taplo:TOML専用のフォーマッターおよびバリデーターで、VS Code拡張機能としても利用可能です。
フォーマット間の変換テクニック
プロジェクトの途中でフォーマットを変更したい場合や、異なるツール間でデータを受け渡す際の変換方法を紹介します。
コマンドラインでの変換
yq:YAML、JSON、TOMLなど複数フォーマット間の変換に対応したコマンドラインツールです。
# YAML → JSON
yq -o=json config.yaml > config.json
# JSON → YAML
yq -P config.json > config.yaml
# YAML → TOML
yq -o=toml config.yaml > config.toml
Python:Pythonのワンライナーでも簡単に変換できます。
# JSON → YAML
python3 -c "import json, yaml, sys; yaml.dump(json.load(sys.stdin), sys.stdout, default_flow_style=False, allow_unicode=True)" < config.json > config.yaml
プログラムからの変換
Node.jsでは、各フォーマットのパーサーライブラリを使って変換できます。
// npm install js-yaml @iarna/toml
const yaml = require('js-yaml');
const toml = require('@iarna/toml');
const fs = require('fs');
// YAML → JSONオブジェクト → TOML
const yamlContent = fs.readFileSync('config.yaml', 'utf8');
const data = yaml.load(yamlContent);
const tomlContent = toml.stringify(data);
fs.writeFileSync('config.toml', tomlContent);
まとめ:プロジェクトに最適なフォーマットを選ぶ
YAML・JSON・TOMLの3つのフォーマットについて、構文の違い、メリット・デメリット、用途別の使い分けを解説しました。
最適なフォーマットの選び方を整理します。
JSON:API通信、プログラム間のデータ交換、ツールが要求する場合(package.json、tsconfig.jsonなど)に使用します。コメントが不要で、機械処理が主な用途の場面に最適です。
YAML:CI/CD設定、Kubernetes、Docker Compose、Ansibleなどインフラ系の設定、人間が頻繁に編集する複雑な構成ファイルに使用します。コメントが書け、可読性が高い反面、インデントや暗黙の型変換に注意が必要です。
TOML:アプリケーション設定、パッケージ管理(Cargo.toml、pyproject.toml)、フラットな構造の設定ファイルに使用します。シンプルで明快な構文が魅力ですが、深いネストには不向きです。
重要なのは、一つのフォーマットに固執するのではなく、用途に応じて最適なものを選ぶことです。リントツールやスキーマバリデーションを活用して、どのフォーマットを使う場合でも設定ファイルの品質を高く保ちましょう。
関連記事
AIエージェント開発入門|自律型AIの仕組みと構築方法を解説【2026年版】
AI駆動コーディングワークフロー|Claude Code・Cursor・Copilotの実践的使い分け
プロンプトエンジニアリング上級編|Chain-of-Thought・Few-Shot・ReActの実践
APIレート制限の設計と実装|トークンバケット・スライディングウィンドウ解説
APIバージョニング戦略|URL・ヘッダー・クエリパラメータの使い分け
BIツール入門|Metabase・Redash・Looker Studioでデータ可視化する方法
チャットボット開発入門|LINE Bot・Slack Botの構築方法と活用事例
CI/CDパイプラインの基礎|継続的インテグレーション・デリバリーの全体像