v1.0.0
2/12/2015 日掲載 – テキスト版

TOML v0.4.0

トムの明瞭で最小の言語の意味。 (By Tom Preston Werner)

注:この仕様はまだ固まっておらず、バージョン1.0になるまでは安定しない可能性があります。

目的

TOMLは明瞭なセマンティクスを持ち、可読性の高い、ミニマルな設定ファイルフォーマットとなることを目的として作られています。TOMLは曖昧さなしに連想配列に変換できるよう設計されていて、 様々な言語上でそれらのデータ構造に展開することが出来ます。

仕様

  • TOMLはケース・センシティブです
  • TOMLファイルはユニコード(UTF-8)でエンコードされている必要があります
  • 空白はタブ(0x09)もしくはスペース(0x20)のことです
  • 改行はLF(0x0A)もしくはCRLF(0x0D0A)です。

コメント

ハッシュ記号(#)に続けて改行までをコメントとします。

# 好きなようにコメントできます。
key = "value" # こんな感じで!

文字列

文字列を記述するには、4種類の方法があります。

基本文字列

基本文字列はクォーテーションマーク(")で囲みます。 クォーテーションマーク、バックスラッシュ、制御文字(U+0000 〜 U+001F)はエスケープする必要があります。その他のユニコード文字は全て文字列内で使えます。

"文字列内では、\"エスケープできます\". Name\tJos\u00E9\nLocation\tSF."

利便性のために、いくつかの文字についてはエスケープシーケンスの短縮形が用意されています。

\b         - backspace       (U+0008)
\t         - tab             (U+0009)
\n         - linefeed        (U+000A)
\f         - form feed       (U+000C)
\r         - carriage return (U+000D)
\"         - quote           (U+0022)
\/         - slash           (U+002F)
\\         - backslash       (U+005C)
\uXXXX     - unicode         (U+XXXX)
\UXXXXXXXX - unicode         (U+XXXXXXXX)

全てのユニコード文字は\uXXXXもしくは\UXXXXXXXXの形式にエスケープできます。エスケープコードは正しいユニコード・スカラ値である必要があります.

上記以外のエスケープシーケンスは将来のために予約されていて、もし使ってしまった場合はTOMLはエラーを出す必要があります。

複数行文字列

ときにはあなたは文書の一節を書いたり、とても長い行を改行したくなることがあるでしょう。TOMLでは、 複数行文字列をクォーテーションマーク3つずつで囲むことで表現できます。文字列の頭にすぐ改行が来た場合はその改行は取り除かれます。その他の空白と改行はそのまま保持されます。

key1 = """
Roses are red
Violets are blue"""

TOMLのパーサは改行をそのプラットフォームに応じて自由に正規化出来ます。

# Unixでは上記のTOMLファイルは以下と同じパース結果になります:
key2 = "Roses are red\nViolets are blue"

# Windowsでは上記のTOMLファイルは以下と同じパース結果になります:
key3 = "Roses are red\r\nViolets are blue"

長い文字列を不要な行頭の空白なしに書きたい場合は、\を行末に書きます。\は全ての空白(もしくは改行)を、空白でない文字が現れるまで取り除きます。もし文字列の最初の文字が\だった場合は、全ての空白文字列と改行を、次の空白でない文字が現れるか、文字列の終わりまで、取り除きます。全てのエスケープシーケンスは基本文字列と同様に複数行文字列でも使えます。

# 以下のそれぞれの文字列は同じとなります:
key1 = "The quick brown fox jumps over the lazy dog."

key2 = """
The quick brown \


fox jumps over \
the lazy dog."""

key3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""

使える文字は、バックスラッシュと制御文字(U+0000 〜 U+001F)以外の全てのユニコード文字です。バックスラッシュと制御文字はエスケープする必要があります。クォーテーションマークは意図しない複数行文字列の終了にならない限りエスケープする必要はありません。

リテラル文字列

あなたがWindowsパスや正規表現を書くことが多い場合、バックスラッシュをエスケープすることは、面倒になったり、間違いやすくなったりします。そのような場合、TOMLはエスケープなしのリテラル形式の文字列をサポートしています(訳注:改行以外は他の制御文字も許容されるようです)。 リテラル文字列はシングル・クォート(')で囲む必要があります。基本文字列のように一行に書きます:

# そのままの文字列を得ることが出来ます.
winpath  = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted   = 'Tom "Dubs" Preston-Werner'
regex    = '<\i\c*\s*>'

複数行リテラル文字列

エスケープが無いため、シングル・クォートはリテラル文字列中では書けません。そのような場合、TOMLはリテラル文字列の複数行版をサポートしています。 複数行リテラル文字列はシングル・クォート3つずつで囲まれていて、改行も許します。リテラル文字列と同様エスケープはありません。文字列の頭の改行は取り除かれます。他の文字列の中身は全て変更なしに読み込まれます。

regex2 = '''I [dw]on't need \d{2} apples'''
lines  = '''
最初の一行は取り除かれて
文字列に展開されます。
その他の空白、改行文字は
保持されます。
'''

もしバイナリデータを使うのでしたら、Base64か、他の適切なASCIIもしくはUTF-8のエンコーディング形式にすることを推奨します。そして、それらのエンコーディングをアプリケーション毎に取り扱う必要があるでしょう。

整数

整数は全ての数のことです(訳注:整数全体のことだと思われる)。正の数を表すときはプラス符号+を前につけても、つけなくても構いません。負の数の場合はマイナス符号-を前につけます。

+99
42
0
-17

大きな数字を表記するために、あなたはアンダースコアを使うことも出来ます。それぞれのアンダースコアは最低1つの数字で囲む必要があります。

1_000
5_349_221
1_2_3_4_5     # valid but inadvisable

整数の表記をゼロから始めることは出来ません。2進数、8進数、16進数の形式で表すことも出来ません。無限や非数を表すことも出来ません。期待される範囲としては、64bit(signed long)となります(−9,223,372,036,854,775,808 〜 9,223,372,036,854,775,807)。

小数

小数は整数部(プラス,マイナス符号をつけてもよい)と、それに続く小数部もしくは指数部から成ります。小数部と指数部の両方で表すことも出来ますが、その場合は小数部を指数部より前に置く必要があります。

# 小数表記
+1.0
3.1415
-0.01

# 指数表記
5e+22
1e6
-2E-2

# 複合
6.626e-34

小数部は小数点の後に数字をならべて表記します。

指数部はE(大文字小文字は問わない)の後に整数(プラス,マイナス符号をつけてもよい)で表記します。

整数と同様、あなたは可読性のためにアンダースコアを使うことも出来ます。それぞれのアンダースコアは最低1つの数字で囲む必要があります。

9_224_617.445_991_228_313
1e1_000

期待される範囲は、64-bit(double)精度です。

ブーリアン

ブーリアン値はただのトークンです(皆がいつも使っているやつです)。小文字のみとします。

true
false

日付

日付型はRFC 3339に準じます。

1979-05-27T07:32:00Z
1979-05-27T00:32:00-07:00
1979-05-27T00:32:00.999999-07:00

配列

配列は角括弧で囲まれたプリミティブ型の集まりです。空白は無視されます。各要素はカンマで区切られます。各データ型を混合させることは出来ません(文字列は全て同じ型だと考えてください)。

[ 1, 2, 3 ]
[ "red", "yellow", "green" ]
[ [ 1, 2 ], [3, 4, 5] ]
[ "全ての", '文字列は', """同じ""", '''型です'''] # この書き方はOk
[ [ 1, 2 ], ["a", "b", "c"] ] # この書き方もOK
[ 1, 2.0 ] # 一つの配列に違う型を混合させるのはダメ

配列は複数行に書くことも出来ます。その場合空白に加えて改行も無視されます。閉じ括弧の前にカンマを書いても構いません。

key = [
1, 2, 3
]

key = [
1,
2, # OK
]

テーブル

テーブル(ハッシュテーブルや連想配列のことです)はキーと値のペアからなる集まりです。それは角括弧で囲まれたテーブル名が書かれた行から始まります。配列は必ず値として表記されるので、テーブルの角括弧と配列は簡単に区別することが出来ます。

[table]

ここに続いて、次のテーブルの開始か、ファイルの終わりまで、キーと値はこのテーブルに属します。等号=の左にキーを、右に値を置きます。キーと値の周りの空白は無視されます。キー、等号、値は同じ行に書く必要があります(ただし値のいくつかは改行を含むことも出来ます)。

キーはクォート(")で囲まんでも囲まなくても構いません。 ベア・キー(クォートで囲まなかった場合)は、使える文字は英数字、アンダースコア、ダッシュのみです(a-zA-Z0-9_-)。 クォーテッド・キー(クォートで囲んだ場合)は、基本文字列と同じルールになり、より多くの文字をキーに使うことが出来ます。ベスト・プラクティスは必要性が生じるまでは囲まない文字列をキーに使うことです。

テーブル内のキーと値の各ペアの順番は保証されません。

[table]
key = "value"
bare_key = "value"
bare-key = "value"

"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"

ドット(.)がベア・キーに使えないのは、ネストしたテーブルを表すのにドットを使うからです。各ドットで分割された部分の命名規則は上記のキーの命名規則に準じます。

[dog."tater.man"]
type = "pug"

これは以下のJSONと同じ構造を表します:

{ "dog": { "tater.man": { "type": "pug" } } }

ドットで分割された部分の周りの空白については無視されます。ただし、周りの空白は使わないことをお勧めします。

[a.b.c]          # ベスト・プラクティスです
[ d.e.f ]        # [d.e.f] と同じです
[ g .  h  . i ]  # [g.h.i] と同じです
[ j . "ʞ" . l ]  # [j."ʞ".l] と同じです

もし、上位のテーブルそのものを記述する必要がないのであれば、省略することも出来ます。

# [x] 省略可
# [x.y] これも可
# [x.y.z] これも省略可
[x.y.z.w] # ここから始めて構いません

空のテーブルは単純にキーと値のペアを書かかないことで作れます。

上位のテーブルの定義を省略した場合、後からそのテーブルの内容を書くことが出来ます(後から書くキーも定義されていない場合のみ)。

[a.b]
c = 1

[a]
d = 2

キーやテーブルを再定義することは出来ません。不正となります。

# やっちゃダメです

[a]
b = 1

[a]
c = 2
# ダメですってば

[a]
b = 1

[a.b]
c = 2

テーブル名、キーを空にすることは出来ません。

# 不正なTOMLです
[]
[a.]
[a..b]
[.b]
[.]
= "no key name" # ダメ

インライン・テーブル

インライン・テーブルはテーブルを表現するためのよりコンパクトな構文です。他の表現だと冗長になるようなグループになったデータを表すのに向いています。インライン・テーブルは波括弧({})で囲まれている必要があります。波括弧の中では、キーと値のペアをカンマ区切りでゼロ個以上置くことが出来ます。値にはインライン・テーブル自体を含む全ての型を使うことが出来ます。

インライン・テーブルは一行で表現されるべきです。波括弧の内側では改行は認められません。ただし、それぞれの値の中で改行することは、それぞれの値型で認められている範囲で出来ます。ですが、出来るとしてもインライン・テーブルを複数行に分割することはなるべく避けるべきです。もしあなたがその必要があるように感じたのならば、普通のテーブルを用いるべきです。

name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }

上記のインライン・テーブルは下記の普通のテーブルと同一の定義です。

[name]
first = "Tom"
last = "Preston-Werner"

[point]
x = 1
y = 2

テーブルの配列

最後の型はテーブルの配列です。テーブル名を角括弧で二重に囲むことで表されます。二重角括弧で囲まれた同じテーブル名を持つテーブルは、配列の要素となります。テーブルは表記順に配列に挿入されます。配列内のキーと値のペアを持たないテーブルは空のテーブルとして扱われます。

[[products]]
name = "Hammer"
sku = 738594937

[[products]]

[[products]]
name = "Nail"
sku = 284758393
color = "gray"

これは以下のJSONと同じ構造を表します:

{
  "products": [
  { "name": "Hammer", "sku": 738594937 },
  { },
  { "name": "Nail", "sku": 284758393, "color": "gray" }
  ]
}

あなたはネストしたテーブルの配列を作ることも出来ます。その場合は、子テーブルにも二重角括弧表記を使ってください。それぞれのテーブルは、その上の最も近い場所に定義されている親テーブルの要素となる配列に属します。

[[fruit]]
name = "apple"

[fruit.physical]
color = "red"
shape = "round"

[[fruit.variety]]
name = "red delicious"

[[fruit.variety]]
name = "granny smith"

[[fruit]]
name = "banana"

[[fruit.variety]]
name = "plantain"

上記のTOMLは下記のJSONに置き換えることができます。

{
  "fruit": [
    {
      "name": "apple",
      "physical": {
        "color": "red",
        "shape": "round"
      },
      "variety": [
        { "name": "red delicious" },
        { "name": "granny smith" }
      ]
    },
    {
      "name": "banana",
      "variety": [
        { "name": "plantain" }
      ]
    }
  ]
}

既にテーブルの配列として定義されたテーブルの後に、同じ名前を持つ通常のテーブルを定義しようとした場合、パースする際にエラーとすべきです。

# 不正なTOMLドキュメント
[[fruit]]
name = "apple"

[[fruit.variety]]
name = "red delicious"

# このテーブルは上のテーブルの配列とコンフリクトを起こします
[fruit.variety]
name = "granny smith"

これって真面目な規格?

YES

なんで作ったの?

私達はきちんと人間が読める、曖昧さなしに連想配列に変換できるフォーマットを必要としていました。そしてYAMLの仕様書は80ページもあって論外だと思ったのです。JSON?検討すらしていません。理由はあなたも分かってるでしょう?

いいね、使ってみよう

でしょでしょ?もしよければプルリク送ってください。もしくはパーサを書くとか。チャレンジしてみて!

TOMLを採用しているプロジェクト

  • Cargo - Rust言語のパッケージマネージャ.
  • InfluxDB - 分散時系列データベース.
  • Heka - Mozillaによるストリーム処理システム.
  • Hugo - Goによる静的サイト・ジェネレータ.

実装

もし実装を作ったのならこのリストに追加してプルリク送ってください。それと、パーサのREADMEには、サポートするTOMLのバージョンをgitのタグかハッシュの形式で書くようお願いします。

バリデータ

言語によらないデコーダとエンコーダのテストスイート

エディタ・サポート

エンコーダ

コンバータ