TOML v1.0.0-rc.2
Tomの明白で最小限な言語。
Tom Preston-Werner, Pradyun Gedam, 他著
目標
TOMLは、明白な意味論により読みやすい、最小限の構成ファイル形式となることを目指しています。TOMLはハッシュテーブルに曖昧さなくマッピングするように設計されています。TOMLは、多種多様な言語でデータ構造に簡単に解析できるはずです。
仕様
- TOMLは大文字と小文字を区別します。
- TOMLファイルは、有効なUTF-8エンコードされたUnicodeドキュメントである必要があります。
- 空白とは、タブ (0x09) またはスペース (0x20) を意味します。
- 改行とは、LF (0x0A) または CRLF (0x0D 0x0A) を意味します。
コメント
ハッシュ記号は、文字列内部を除き、その行の残りをコメントとしてマークします。
# This is a full-line comment
key = "value" # This is a comment at the end of a line
another = "# This is not a comment"
タブ以外の制御文字 (U+0000 から U+0008、U+000A から U+001F、U+007F) はコメント内では許可されていません。
キー/値のペア
TOMLドキュメントの主要な構成要素は、キー/値のペアです。
キーは等号の左側に、値は右側にあります。キー名と値の周りの空白は無視されます。キー、等号、および値は同じ行にある必要があります(ただし、一部の値は複数行に分割できます)。
key = "value"
値は、次のいずれかの型を持つ必要があります。
未指定の値は無効です。
key = # INVALID
キー/値のペアの後には改行(またはEOF)が必要です。(例外については、インラインテーブルを参照してください。)
first = "Tom" last = "Preston-Werner" # INVALID
キー
キーは、ベア、引用符付き、またはドット付きのいずれかになります。
ベアキーには、ASCII文字、ASCII数字、アンダースコア、およびダッシュ(A-Za-z0-9_-
)のみを含めることができます。ベアキーはASCII数字のみで構成できます(例:1234
)が、常に文字列として解釈されることに注意してください。
key = "value"
bare_key = "value"
bare-key = "value"
1234 = "value"
引用符付きキーは、基本文字列またはリテラル文字列とまったく同じ規則に従い、より幅広いキー名を使用できます。絶対に必要でない限り、ベアキーを使用するのが最善の方法です。
"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"
'key2' = "value"
'quoted "value"' = "value"
ベアキーは空であってはなりませんが、空の引用符付きキーは許可されています(推奨されませんが)。
= "no key name" # INVALID
"" = "blank" # VALID but discouraged
'' = 'blank' # VALID but discouraged
ドット付きキーは、ドットで結合されたベアキーまたは引用符付きキーのシーケンスです。これにより、類似のプロパティをグループ化できます。
name = "Orange"
physical.color = "orange"
physical.shape = "round"
site."google.com" = true
JSONの世界では、次の構造になります。
{
"name": "Orange",
"physical": {
"color": "orange",
"shape": "round"
},
"site": {
"google.com": true
}
}
ドットで区切られた部分の周りの空白は無視されますが、余分な空白を使用しないのが最善の方法です。
キーを複数回定義することは無効です。
# DO NOT DO THIS
name = "Tom"
name = "Pradyun"
ベアキーと引用符付きキーは同等であることに注意してください。
# THIS WILL NOT WORK
spelling = "favorite"
"spelling" = "favourite"
キーが直接定義されていない限り、キーとその内部の名前を書き込むことができます。
# This makes the key "fruit" into a table.
fruit.apple.smooth = true
# So then you can add to the table "fruit" like so:
fruit.orange = 2
# THE FOLLOWING IS INVALID
# This defines the value of fruit.apple to be an integer.
fruit.apple = 1
# But then this treats fruit.apple like it's a table.
# You can't turn an integer into a table.
fruit.apple.smooth = true
ドット付きキーを順序どおりに定義しないことは推奨されていません。
# VALID BUT DISCOURAGED
apple.type = "fruit"
orange.type = "fruit"
apple.skin = "thin"
orange.skin = "thick"
apple.color = "red"
orange.color = "orange"
# RECOMMENDED
apple.type = "fruit"
apple.skin = "thin"
apple.color = "red"
orange.type = "fruit"
orange.skin = "thick"
orange.color = "orange"
ベアキーはASCII整数のみで構成できるため、浮動小数点数のように見えるが2つの部分からなるドット付きキーを記述することができます。それをする正当な理由がない限り、これを行わないでください(おそらく理由はないでしょう)。
3.14159 = "pi"
上記のTOMLは、次のJSONにマッピングされます。
{ "3": { "14159": "pi" } }
文字列
文字列を表現する方法は4つあります。基本、複数行基本、リテラル、複数行リテラルです。すべての文字列には、有効なUTF-8文字のみが含まれている必要があります。
基本文字列は引用符("
)で囲まれています。タブ以外の制御文字(U+0000からU+0008、U+000AからU+001F、U+007F)と、エスケープする必要がある引用符、バックスラッシュを除くすべてのUnicode文字を使用できます。
str = "I'm a string. \"You can quote me\". 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)
\\ - backslash (U+005C)
\uXXXX - unicode (U+XXXX)
\UXXXXXXXX - unicode (U+XXXXXXXX)
任意のUnicode文字は、\uXXXX
または\UXXXXXXXX
の形式でエスケープできます。エスケープコードは、有効なUnicodeスカラ値である必要があります。
上記にリストされていない他のすべてのエスケープシーケンスは予約されています。使用すると、TOMLはエラーを生成する必要があります。
テキストの段落(例:翻訳ファイル)を表現する必要がある場合や、非常に長い文字列を複数行に分割したい場合があります。TOMLはこれを簡単に行うことができます。
複数行基本文字列は、両側に3つの引用符で囲まれ、改行を許可します。開始デリミターの直後の改行はトリミングされます。その他の空白文字と改行文字はすべてそのまま残ります。
str1 = """
Roses are red
Violets are blue"""
TOMLパーサーは、プラットフォームにとって理にかなった改行に自由に正規化できます。
# On a Unix system, the above multi-line string will most likely be the same as:
str2 = "Roses are red\nViolets are blue"
# On a Windows system, it will most likely be equivalent to:
str3 = "Roses are red\r\nViolets are blue"
余分な空白を導入せずに長い文字列を記述するには、「行末バックスラッシュ」を使用します。行の最後の空白以外の文字がエスケープされていない\
の場合、次の空白以外の文字または終了デリミターまでのすべての空白(改行を含む)と一緒にトリミングされます。基本文字列に有効なすべてのエスケープシーケンスは、複数行の基本文字列にも有効です。
# The following strings are byte-for-byte equivalent:
str1 = "The quick brown fox jumps over the lazy dog."
str2 = """
The quick brown \
fox jumps over \
the lazy dog."""
str3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
タブ、改行、およびキャリッジリターン(U+0000〜U+0008、U+000B、U+000C、U+000E〜U+001F、U+007F)以外の制御文字と、エスケープする必要があるバックスラッシュを除くすべてのUnicode文字を使用できます。
複数行の基本文字列の内側の任意の場所に、引用符、または2つの隣接する引用符を記述できます。それらはデリミターのすぐ内側にも記述できます。
str4 = """Here are two quotation marks: "". Simple enough."""
# str5 = """Here are three quotation marks: """.""" # INVALID
str5 = """Here are three quotation marks: ""\"."""
str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
# "This," she said, "is just a pointless statement."
str7 = """"This," she said, "is just a pointless statement.""""
Windowsパスまたは正規表現を頻繁に指定する場合は、バックスラッシュをエスケープする必要があるため、すぐに面倒になり、エラーが発生しやすくなります。これを支援するために、TOMLはエスケープをまったく許可しないリテラル文字列をサポートしています。
リテラル文字列は、単一引用符で囲まれています。基本文字列と同様に、単一行に表示される必要があります。
# What you see is what you get.
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 = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
複数行リテラル文字列内の任意の場所に1つまたは2つの単一引用符を記述できますが、3つ以上の単一引用符のシーケンスは許可されていません。
quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
apos15 = "Here are fifteen apostrophes: '''''''''''''''"
# 'That,' she said, 'is still pointless.'
str = ''''That,' she said, 'is still pointless.''''
タブ以外の制御文字は、リテラル文字列では許可されていません。したがって、バイナリデータの場合、Base64またはその他の適切なASCIIまたはUTF-8エンコーディングを使用することをお勧めします。そのエンコーディングの処理は、アプリケーション固有になります。
整数
整数は整数です。正の数にはプラス記号を付けることができます。負の数にはマイナス記号を付けます。
int1 = +99
int2 = 42
int3 = 0
int4 = -17
大きな数値の場合は、読みやすくするために数字の間にアンダースコアを使用できます。各アンダースコアは、両側に少なくとも1つの数字で囲む必要があります。
int5 = 1_000
int6 = 5_349_221
int7 = 53_49_221 # Indian number system grouping
int8 = 1_2_3_4_5 # VALID but discouraged
先頭のゼロは許可されていません。整数値-0
と+0
は有効であり、プレフィックスなしのゼロと同じです。
負でない整数値は、16進数、8進数、または2進数で表すこともできます。これらの形式では、先頭の+
は許可されておらず、先頭のゼロは許可されています(プレフィックスの後)。16進値は大文字と小文字を区別しません。アンダースコアは数字の間で許可されます(プレフィックスと値の間ではありません)。
# hexadecimal with prefix `0x`
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef
# octal with prefix `0o`
oct1 = 0o01234567
oct2 = 0o755 # useful for Unix file permissions
# binary with prefix `0b`
bin1 = 0b11010110
任意の64ビット符号付き整数(−2^63から2^63−1)を受け入れて、損失なく処理する必要があります。整数を損失なく表現できない場合は、エラーをスローする必要があります。
浮動小数点数
浮動小数点数は、IEEE 754 binary64値として実装する必要があります。
浮動小数点数は、整数部分(10進整数の値と同じ規則に従います)と、その後に小数部分および/または指数部分が続きます。小数部分と指数部分の両方が存在する場合、小数部分は指数部分の前になければなりません。
# fractional
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01
# exponent
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2
# both
flt7 = 6.626e-34
小数部分は、小数点とそれに続く1つ以上の数字です。
指数部分は、E(大文字または小文字)とそれに続く整数部分(10進整数の値と同じ規則に従いますが、先頭にゼロを含めることができます)です。
小数点を使用する場合、両側に少なくとも1つの数字で囲む必要があります。
# INVALID FLOATS
invalid_float_1 = .7
invalid_float_2 = 7.
invalid_float_3 = 3.e+20
整数と同様に、読みやすくするためにアンダースコアを使用できます。各アンダースコアは、少なくとも1つの数字で囲む必要があります。
flt8 = 224_617.445_991_228
浮動小数点数値-0.0
および+0.0
は有効であり、IEEE 754に従ってマッピングする必要があります。
特別な浮動小数点数値も表現できます。常に小文字です。
# infinity
sf1 = inf # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity
# not a number
sf4 = nan # actual sNaN/qNaN encoding is implementation-specific
sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation-specific
真偽値
ブール値は、使い慣れたトークンです。常に小文字です。
bool1 = true
bool2 = false
オフセット付き日時
特定の時点を明確に表すには、RFC 3339形式のオフセット付き日時を使用できます。
odt1 = 1979-05-27T07:32:00Z
odt2 = 1979-05-27T00:32:00-07:00
odt3 = 1979-05-27T00:32:00.999999-07:00
読みやすくするために、日時間のTデリミターをスペース文字に置き換えることができます(RFC 3339セクション5.6で許可されているように)。
odt4 = 1979-05-27 07:32:00Z
ミリ秒の精度が必要です。小数秒のそれ以上の精度は実装固有です。値に実装がサポートできる以上の精度が含まれている場合、追加の精度は切り捨てられ、丸められません。
ローカル日時
RFC 3339形式の日時からオフセットを省略すると、オフセットやタイムゾーンに関係なく、指定された日時を表します。追加情報がないと、特定の時点に変換できません。必要な場合、特定の時点への変換は実装固有です。
ldt1 = 1979-05-27T07:32:00
ldt2 = 1979-05-27T00:32:00.999999
ミリ秒の精度が必要です。小数秒のそれ以上の精度は実装固有です。値に実装がサポートできる以上の精度が含まれている場合、追加の精度は切り捨てられ、丸められません。
ローカル日付
RFC 3339形式の日時の日付部分のみを含めると、オフセットやタイムゾーンに関係なく、その日全体を表します。
ld1 = 1979-05-27
ローカル時間
RFC 3339形式の日時の時間部分のみを含めると、特定の日やオフセットやタイムゾーンに関係なく、その時刻を表します。
lt1 = 07:32:00
lt2 = 00:32:00.999999
ミリ秒の精度が必要です。小数秒のそれ以上の精度は実装固有です。値に実装がサポートできる以上の精度が含まれている場合、追加の精度は切り捨てられ、丸められません。
配列
配列は、中に値がある角括弧です。空白は無視されます。要素はコンマで区切られます。配列には、キー/値のペアで許可されているのと同じデータ型の値を含めることができます。異なる型の値を混在させることができます。
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_array_of_int = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]
# Mixed-type arrays are allowed
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
"Foo Bar <foo@example.com>",
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]
配列は複数行にまたがることができます。配列の最後の値の後に、終端コンマ(末尾コンマとも呼ばれます)があってもかまいません。値の前と閉じ括弧の前に、任意の数の改行とコメントを含めることができます。
integers2 = [
1, 2, 3
]
integers3 = [
1,
2, # this is ok
]
テーブル
テーブル(ハッシュテーブルまたは辞書とも呼ばれます)は、キー/値のペアのコレクションです。テーブルは、それ自体で1行の角括弧で表示されます。配列は値にしかならないため、配列と区別できます。
[table]
その下と、次のテーブルまたはEOFまでがそのテーブルのキー/値です。テーブル内のキー/値のペアは、特定の順序であることは保証されていません。
[table-1]
key1 = "some string"
key2 = 123
[table-2]
key1 = "another string"
key2 = 456
テーブルの名前付け規則は、キーと同じです(上記のキーの定義を参照)。
[dog."tater.man"]
type.name = "pug"
JSONの世界では、次の構造になります。
{ "dog": { "tater.man": { "type": { "name": "pug" } } } }
キーの周りの空白は無視されますが、余分な空白を使用しないのが最善の方法です。
[a.b.c] # this is best practice
[ d.e.f ] # same as [d.e.f]
[ g . h . i ] # same as [g.h.i]
[ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
必要がない場合は、すべてのスーパテーブルを指定する必要はありません。TOMLはそれを行う方法を知っています。
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
[x] # defining a super-table afterward is ok
空のテーブルは許可されており、単にキー/値のペアがありません。
キーと同様に、テーブルを複数回定義することはできません。そうすると無効になります。
# DO NOT DO THIS
[fruit]
apple = "red"
[fruit]
orange = "orange"
# DO NOT DO THIS EITHER
[fruit]
apple = "red"
[fruit.apple]
texture = "smooth"
テーブルを順序どおりに定義しないことは推奨されていません。
# VALID BUT DISCOURAGED
[fruit.apple]
[animal]
[fruit.orange]
# RECOMMENDED
[fruit.apple]
[fruit.orange]
[animal]
ドット付きキーは、各ドットの左側にあるすべてをテーブルとして定義します。テーブルは複数回定義できないため、[table]
ヘッダーを使用してそのようなテーブルを再定義することは許可されていません。同様に、ドット付きキーを使用して、[table]
形式ですでに定義されているテーブルを再定義することも許可されていません。
ただし、[table]
形式を使用して、ドット付きキーで定義されたテーブル内のサブテーブルを定義できます。
[fruit]
apple.color = "red"
apple.taste.sweet = true
# [fruit.apple] # INVALID
# [fruit.apple.taste] # INVALID
[fruit.apple.texture] # you can add sub-tables
smooth = true
インラインテーブル
インラインテーブルは、テーブルを表現するためのよりコンパクトな構文を提供します。これらは、冗長になりがちなグループ化されたデータに特に役立ちます。インラインテーブルは、中括弧:{
と}
で囲まれています。中括弧内には、ゼロ以上のコンマ区切りのキー/値のペアが表示される場合があります。キー/値のペアは、標準テーブルのキー/値のペアと同じ形式を取ります。インラインテーブルを含むすべての値型が許可されています。
インラインテーブルは、1行で表示されることを意図しています。インラインテーブルの最後のキー/値ペアの後には、終端のカンマ(末尾のカンマとも呼ばれます)は許可されません。値の中で有効な場合を除き、中括弧の間に改行は許可されません。そうであっても、インラインテーブルを複数行に分割することは強く推奨されません。もしそのような欲求に駆られるなら、それは標準テーブルを使用すべきであることを意味します。
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type.name = "pug" }
上記のインラインテーブルは、以下の標準テーブル定義と同一です。
[name]
first = "Tom"
last = "Preston-Werner"
[point]
x = 1
y = 2
[animal]
type.name = "pug"
インラインテーブルは、その中のキーとサブテーブルを完全に定義します。新しいキーやサブテーブルを追加することはできません。
[product]
type = { name = "Nail" }
# type.edible = false # INVALID
同様に、インラインテーブルを使用して、既に定義されているテーブルにキーやサブテーブルを追加することもできません。
[product]
type.name = "Nail"
# type = { edible = false } # INVALID
テーブルの配列
まだ説明されていない最後の構文では、テーブルの配列を記述できます。これは、二重角括弧で囲まれたテーブル名を使用することで表現できます。その下、そして次のテーブルまたはEOFまで、そのテーブルのキー/値が記述されます。同じ二重角括弧で囲まれた名前を持つ各テーブルは、テーブルの配列の要素になります。テーブルは、出現した順序で挿入されます。キー/値のペアがない二重角括弧で囲まれたテーブルは、空のテーブルと見なされます。
[[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] # subtable
color = "red"
shape = "round"
[[fruit.variety]] # nested array of tables
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" }
]
}
]
}
テーブルまたはテーブルの配列の親が配列要素である場合、子を定義する前に、その要素が既に定義されている必要があります。その順序を逆にしようとすると、解析時にエラーが発生する必要があります。
# INVALID TOML DOC
[fruit.physical] # subtable, but to which parent element should it belong?
color = "red"
shape = "round"
[[fruit]] # parser must throw an error upon discovering that "fruit" is
# an array rather than a table
name = "apple"
静的に定義された配列に、その配列が空であっても、追加しようとすると、解析時にエラーが発生する必要があります。
# INVALID TOML DOC
fruit = []
[[fruit]] # Not allowed
既に確立された配列と同じ名前で通常のテーブルを定義しようとすると、解析時にエラーが発生する必要があります。同様に、通常のテーブルを配列として再定義しようとすると、解析時にエラーが発生する必要があります。
# INVALID TOML DOC
[[fruit]]
name = "apple"
[[fruit.variety]]
name = "red delicious"
# INVALID: This table conflicts with the previous array of tables
[fruit.variety]
name = "granny smith"
[fruit.physical]
color = "red"
shape = "round"
# INVALID: This array of tables conflicts with the previous table
[[fruit.physical]]
color = "green"
必要に応じてインラインテーブルを使用することもできます。
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
ファイル名拡張子
TOMLファイルは、拡張子.toml
を使用する必要があります。
MIMEタイプ
インターネット経由でTOMLファイルを転送する場合、適切なMIMEタイプはapplication/toml
です。