💕

TOML っていいな

2022/07/10に公開

TL;DR

TOML ってなに

設定ファイルのフォーマット。 json とか yaml みたいなもんと思ってよさそう。

TOML ってどんな見た目なの

ここ から丸パクリしました。

# TOMLドキュメントの例です。

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # 日付はファーストクラスのデータ型です。

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

[servers]

  # タブもしくはスペースで自由にインデントできます。
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

[clients]
data = [ ["gamma", "delta"], [1, 2] ]

# 配列内の改行ももちろんOK!
hosts = [
  "alpha",
  "omega"
]

これは以下のような json と同じです。

{
  "title": "TOML Example",
  "owner": {
    "dob": "1979-05-27T07:32:00-08:00",
    "name": "Tom Preston-Werner"
  },
  "database": {
    "connection_max": 5000,
    "enabled": true,
    "ports": [
      8001,
      8001,
      8002
    ],
    "server": "192.168.1.1"
  },
  "servers": {
    "alpha": {
      "dc": "eqdc10",
      "ip": "10.0.0.1"
    },
    "beta": {
      "dc": "eqdc10",
      "ip": "10.0.0.2"
    }
  },
  "clients": {
    "data": [
      [
        "gamma",
        "delta"
      ],
      [
        1,
        2
      ]
    ],
    "hosts": [
      "alpha",
      "omega"
    ]
  }
}

yaml だと以下

title: TOML Example
owner:
  dob: 1979-05-27T07:32:00-08:00
  name: Tom Preston-Werner
database:
  connection_max: 5000
  enabled: true
  ports:
  - 8001
  - 8001
  - 8002
  server: 192.168.1.1
servers:
  alpha:
    dc: eqdc10
    ip: 10.0.0.1
  beta:
    dc: eqdc10
    ip: 10.0.0.2
clients:
  data:
  - - gamma
    - delta
  - - 1
    - 2
  hosts:
  - alpha
  - omega

TOML のうれしいところ

コメントが書ける

# 以降はコメント。

# https://toml.io/ja/v0.5.0#%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88
# 好きなようにコメントできます。
key = "value" # 行末までコメントです。

深い階層の配列への要素追加の diff がみやすい

たとえば、以下のような YAML があったとします。

clients:
  data:
  - - alpha
    - beta
  - - 1
    - 2

json にすると以下のような構造です。

{
  "clients": {
    "data": [
      [
        "alpha",
        "beta"
      ],
      [
        1,
        2
      ]
    ]
  }
}

ここに gamma 3 を追加したいとします。 json だと以下のようになってほしい。

{
  "clients": {
    "data": [
      [
        "alpha",
        "beta",
        "gamma"
      ],
      [
        1,
        2,
        3
      ]
    ]
  }
}

上記の yaml に以下のような変更を加えたとします。以下の yaml への diff は正しいでしょうか?

    - - alpha
      - beta
+     - gamma
    - - 1
      - 2
+   - 3

答えは 正しくない です。

正しい diff はこう。

    - - alpha
      - beta
+     - gamma
    - - 1
      - 2
+     - 3

違いは - 3 の前のスペースの数です。

このくらいの量なら注意深く見ていれば気が付けるかもしれませんが、レビューでこの違いに気が付けない場合もあります。
大量のデータがあるときなどですね。
github の diff 表示行はそこまで多くないため、ファイルそのものを見てレビューする必要があります。非常に厳しい。

これが TOML だと以下のような記述ができます。

[clients]
  data = [
    [
      "alpha",
      "beta",
    ],
    [
      1,
      2,
    ],
  ]

しかもこれは、 インデントの違いはパース結果の差異を産みません!
上記の TOML と下記の TOML にパース結果の違いはありません。

[clients]
  data = [
    ["alpha", "beta",],
    [1, 2,],
  ]

これはとてもうれしい。

とにかく以下のように、意図している閉じカッコのなかに意図する文字列が入ってさえいればよいわけです。

        "alpha",
        "beta",
+       "gamma",
      ],
      [
        1,
        2,
+       3,
      ],
    ]

気にすべきは閉じカッコだけ!
これは非常にレビューがしやすい。

TOML 書いてみたい!手軽に書いてパースできる?

筆者は以下のように見てる。(慣れてきたら json で確認要らなくなってくるけど)

$ cat example.toml | dasel -r toml -w json
{
  "clients": {
    "data": [
      [
        "alpha",
        "beta"
      ],
      [
        1,
        2
      ]
    ]
  }
}

https://github.com/TomWright/dasel

余談: jsonc, json5 でいいのでは?

正直自分も将来的には jsonc, json5 のほうが TOML より好きになる可能性もあるとは思ってます。
でも現段階では TOML のほうが多言語での利用が比較的しやすいし、ググラビリティも高いし、公式資料もシンプル明快なので TOML に軍配が上がるかなというスタンスです。

さいごに

じつのところ、この記事で分かることはすべて https://toml.io/ja/v0.5.0 を読めばわかることです。
大したことは書いてませんでしたが、こんな記事をわざわざ書くくらい TOML が好きな人間が一人いることを残したかったので記事を書きました。
TOML はいいぞ。

GitHubで編集を提案

Discussion