広告が嫌いですか? 行く 広告なし 今日

TOML と YAML と JSON — 設定フォーマットの「あなたを怒らせる量」によるランキング

更新日

すべての設定フォーマットは、最終的にあなたを裏切ります。YAMLのインデントの苦悩と静かなブール型の変換、JSONのコメントなしのポリシー、TOMLの「待って、この構文は何か?」という瞬間。それぞれのフォーマットがもたらす実際のコストと、どの場合にどのフォーマットを選ぶべきかを示します。

TOML と YAML と JSON — 設定フォーマットがあなたを怒らせる度合いで順位付け 1

すべてのプロジェクトは、最終的に設定フォーマットを選ぶことになります。YAMLはあらゆる場所に見られます。JSONはあなたの同僚たちよりも古いものです。TOMLは、その「実は、これは設計されたものだ」という声を上げて登場しました。すべてのフォーマットは最終的にあなたを裏切ります。その裏切りは、単に異なるだけです。

ここに直接比較を示します — 同じ設定、3つのフォーマット — そしてそれぞれが、あなたの人生の選択を後悔させるタイミングを正確に示します。

同じ設定、3つの方法

基本的なウェブアプリ設定:名前、ポート、デバッグフラグ、バージョン文字列、データベース設定、許可されたオリジン。何らかの特殊な機能はありません。ここからフォーマットの違いが現れます。

トムル

# App configuration
[app]
name = "my-app"
port = 3000
debug = false
version = "1.2.3"
allowed_origins = ["https://example.com", "https://api.example.com"]

[database]
host = "localhost"
port = 5432
name = "mydb"

ヤム

# App configuration
app:
  name: my-app
  port: 3000
  debug: false
  version: "1.2.3"
  allowed_origins:
    - https://example.com
    - https://api.example.com

database:
  host: localhost
  port: 5432
  name: mydb

翻訳

{
  "app": {
    "name": "my-app",
    "port": 3000,
    "debug": false,
    "version": "1.2.3",
    "allowed_origins": [
      "https://example.com",
      "https://api.example.com"
    ]
  },
  "database": {
    "host": "localhost",
    "port": 5432,
    "name": "mydb"
  }
}

一目でわかる

特徴トムルヤム翻訳
コメント✅ はい✅ はい❌ いいえ
型推論明示的積極的(しばしば誤り)明示的
配列= ["a", "b"]- item またはインライン["a", "b"]
終端カンマ該当なし該当なし❌ 非法
深くネストされた設定文書がすぐに長くなる読みやすさがある長くても明確
型の安定性TOML 1.0(2021年、安定版)1.1 と 1.2 のパーサーの混乱安定
null サポート❌ null 型ではない✅ はい (~ または null)✅ はい (null)
パーセントエンコードされる必要がありますCargo.toml、pyproject.tomlGitHub Actions、k8s、Dockerpackage.json、tsconfig.json

YAML:最も読みやすいが、それがなくなるまで

YAMLはデモでは素晴らしいように見えます。フラットな設定はほとんど文章のように見えます。しかし、そのエッジケースに到達すると、その設定ファイルはすでにインフラとしての役割を果たしています。

ノルウェー問題

YAML 1.1 — ほとんどのパーサーがデフォルトで使用している — これらの値はすべてブール値です: y, n, yes, no, on, off, true, false。したがって country: NOcountry: falseと解釈されます。これが「ノルウェー問題」と呼ばれる本当の理由です。 ノルウェー問題 — ノルウェーの国コードは NOです。PyYAMLはv6.0(2022年にリリース)でこれを修正しました。SnakeYAML(多くのJavaツールで使用)はまだ完全に解決していません。設定値に no または yes を使用する前に、パーサーを確認してください。

型推論が間違える

YAMLにおける未引用値は型を強制的に変換されます。 port: 8080 は整数になります。 version: 1.10 は浮動小数点数になります 1.1 — 数学的には等しくても、意味的には誤りです。バージョン文字列を引用していないと、アプリがv1.1ではなくv1.10と認識していることに10分も驚き、その原因を理解できなくなるでしょう。解決策は単純です:すべての文字列として扱うべき値を引用してください。しかしYAMLはそれを強制していませんので、そうしません。

インデントはインフラとしての役割を果たす

YAMLではタブは違法です — 避けるべきではなく、違法です。ファイル内で2スペースと4スペースのインデントを混ぜると、パースエラーが発生し、そのエラーはしばしば誤った行を指します。GitHub Actionsではこの問題が最も鋭いエッジです:誤ったインデントの run: ブロックは実行時ではなくパース時に失敗し、ワークフロー実行者は構文のみを検証するため、ステップ構造を検証しません。CIジョブから「予期しない値」というエラーが発生し、どのステップが破損したかの情報がないため、20分もデバッグ出力を追加する必要があります。問題の原因は、4スペースインデントが2スペースだったことでした。

もしYAMLが不一致なインデントのまみれになっているなら、 YAMLフォーマッター がデバッグを開始する前にそれを正規化します。

TOML:設定に本当に考えたフォーマット

GitHubの共同創業者であるTom Preston-Wernerが、不一致なパース行動を持つINIスタイルの設定や、彼に驚かせるYAML設定に疲れてTOMLを作成しました。TOML 1.0は2021年1月に、数年間の修正の後でリリースされました。現在、Rustプロジェクト(Cargo.toml)、Pythonパッケージング(pyproject.toml)、およびHugoサイトの標準となっています。仕様は安定しており、パーサーは一貫しており、型システムも期待通りに動作します。

何を正しく得ているか

  • 予期しない型変換がありません。 version = "1.10" は常に文字列です。 port = 3000 は常に整数です。あなたが書いたものは、あなたが得るものです。
  • コメントは、あなたが期待するように動作します(# 行末まで)、JSONとは異なります。
  • フラットな設定から中程度のネストまでが、深くネストされたJSONとは異なり、本当に読みやすくなります。

配列のテーブル構文

TOMLの主な課題は、配列のテーブル構文です。複数のデータベース接続のようなオブジェクトの配列が必要な場合、その構文は次のようになります:

[[databases]]
name = "primary"
host = "db1.example.com"

[[databases]]
name = "replica"
host = "db2.example.com"

[[double bracket]] セクションは databases 配列の1つの項目です。これは機能します。明確です。しかし、初めてTOMLファイルを開く開発者はすべて「これはINIですか?」と尋ねます — なぜなら、それは少しINIのように見えているからです。この不慣れは、TOMLを初めて見る貢献者を採用する際に、実際のコストをもたらします。

TOMLはさらに null 型を持ちません — 意図的にです。あなたのスキーマがnullを「キーが存在しているが明示的に設定されていない」という意味に使う場合、そのようにモデル化する必要があります(キーを完全に省略する、またはセンチネル値を使用する)。そして、深くネストされた設定はすぐに長くなる:TOMLはYAMLのアンカー/アライアスシステムを持たず、設定に繰り返し構造がある場合、大量のコピー&ペーストが必要になります。

TOMLフォーマッター が、時間とともに自然に成長したTOMLファイルを整理するときに便利です。

JSON:あなたが知っている悪魔

JSONはデータ交換 — マシンがマシンと話すために — 用意されたものであり、人間が設定ファイルを書くために設計されたものではありません。すべての言語がすでにJSONパーサーを持っているため、その便利さが勝ちました。現在、JavaScriptプロジェクトにはpackage.json、tsconfig.json、.eslintrc.json、および概ね40のJSON設定ファイルがあります。すべてを手動で編集します。

コメントなし。まだ。

ドーガス・クロックフォードは2012年にJSONにコメントを削除した — 開発者がパーサーのディレクティブとしてそれを使用するのを懸念したためです。インターネットはそれ以来毎日この問題を批判しています。人々が使う対処法は:

  • JSONC — コメント付きのJSON。VS Codeはこれを settings.jsonlaunch.jsonで使用しています。標準JSONパーサーでは解析できません。非標準です。
  • JSON5 — コメント、終端のコンマ、未引用のキー、複数行の文字列を追加します。仕様と独立したパーサーを持ちます。Babelはこれを設定ファイルで使用しています。それでも標準JSONではありません。
  • "_comment" key — 文字列フィールドにコメントテキストを保持します。機能しますが、見かけはひどいです。データモデルに影響します。

末尾カンマ

また違法です。配列またはオブジェクトの最後の項目の後にコンマを追加すると JSON.parseSyntaxError: Unexpected token } と表示され、問題があることを示しますが、誤ったコンマの場所を示しません。これは人間が手動で書いた設定ファイルにおけるJSONパースエラーの1位であり、それはJavaScript配列、Pythonリスト、Rust enumなど、すべての現代言語がトリーリングコンマを許容しているため、人間が手動でJSONを書く習慣から来ています。

JSONが正しく得ている点

型システムは明確で、すべての言語のJSONパーサーが一致しています。すべての true, 1, "1"と、 null が意味するものに一致します。JSONスキーマは、3つのフォーマットの中で最も成熟した設定検証オプションです — VS Codeはtsconfig.jsonおよびpackage.jsonのインラインエラー強調でそれを使用しています。ツールがJSONを生成する場合(webpack、tsc、npm)、読める必要性はもうありません — それは JSONフォーマッタ がそのためにあるのです。

結論:文脈に基づいて選ぶべきであり、好みに基づくべきではない

ツールが生成または消費する場合にJSONを使用してください(package.json、tsconfig、AWS設定、GitHub APIレスポンス)、またはJSONスキーマ検証が必要な場合。手動で書く必要以上に抵抗しないでください。コメントの欠如は問題ですが、普及とツールサポートは議論の余地がありません。 人間が主に作成し、相対的にフラットな設定の場合にYAMLを使用してください — GitHub Actionsワークフロー、Docker Composeファイル、Kubernetesマニフェスト。ブールまたは数字に誤解される可能性のある値(バージョン文字列、国コード、数字で始まるもの)をすべて引用してください。リーダーを実行してください。タブは絶対に使用しないでください。型推論をバグと見なしてください。

フォーマットの選択を完全に制御し、予期しない型変換を避けたい場合にTOMLを使用してください。3つのフォーマットの中で最も誠実です。新しいプロジェクトを開始し、ツールがフォーマットを強制していない場合、6ヶ月後に驚かれないようにTOMLが最も適しています。不慣れは一時的なコストであり、明確性は永久です。 設定が主に人間が作成し、相対的に平坦である場合——GitHub Actions のワークフロー、Docker Compose ファイル、Kubernetes マニフェスト。誤ってブール値または数値に見えるものを引用(バージョン文字列、国コード、数字で始まるもの)。リーダーを実行する。タブを一切使用しない。型推論をバグと見なし、機能とは見なさない。

TOMLを使用する フォーマットの選択を制御し、驚きの型の自動変換を避けたい場合。三つのフォーマットの中で、それが何であるかを最も誠実に表現している。新しいプロジェクトを開始し、ツールがフォーマットを強制していない場合、6ヶ月後に驚きを感じにくくなる。不慣れは一時的なコストであり、明確性は永久に続く。

広告なしで楽しみたいですか? 今すぐ広告なしで

拡張機能をインストールする

お気に入りのブラウザにIOツールを追加して、すぐにアクセスし、検索を高速化します。

に追加 Chrome拡張機能 に追加 エッジ拡張 に追加 Firefox 拡張機能 に追加 Opera 拡張機能

スコアボードが到着しました!

スコアボード ゲームを追跡する楽しい方法です。すべてのデータはブラウザに保存されます。さらに多くの機能がまもなく登場します!

ニュースコーナー 技術ハイライト付き

参加する

価値ある無料ツールの提供を継続するためにご協力ください

コーヒーを買って