MessagePack 仕様
このドキュメントは、MessagePackの仕様(MessagePack specification)の和訳です。
MessagePackは、JSONのようなオブジェクトをシリアライズするデータ交換フォーマットです。
MessagePackには、型システムとフォーマットの2つの概念があります。
シリアライズとは、MessagePack型システムを介してアプリケーションオブジェクトからMessagePack形式へ変換することを指します。
デシリアライズとは、MessagePack型システムを介してMessagePack形式からアプリケーションオブジェクトへ変換することを指します。
シリアライズ:
アプリケーションオブジェクト
--> MessagePack型システム
--> MessagePack形式(バイト配列)
デシリアライズ:
MessagePack形式(バイト配列)
--> MessagePack型システム
--> アプリケーションオブジェクト
このドキュメントでは、MessagePack型システム、フォーマット、およびそれらの変換について説明します。
型システム
- Integerは整数を表します。
- Nilはnilを表します。
- Booleanは真または偽を表します。
- FloatはNaNとInfinityを含むIEEE 754倍精度浮動小数点数を表します。
-
Raw
- Raw型を拡張したStringはUTF-8文字列を表します。
- Raw型を拡張したBinaryはバイト配列を表します。
- Arrayはオブジェクトのシーケンスを表します。
- Mapはオブジェクトのキーと値のペアを表します。
-
ExtensionはアプリケーションやMessagePack仕様で定義される整数です。
- Timestampは、タイムゾーンやカレンダーに依存しない、世界の時間軸上の時刻を表します。最大精度はナノ秒です。
TimestampはUNIX時間のことです。
制限
-
Integerオブジェクトの値は
-(2^63)
から(2^64)-1
までです。 -
Binaryオブジェクトの最大長は
(2^32)-1
です。 -
Stringオブジェクトの最大バイトサイズは
(2^32)-1
です。 -
Stringオブジェクトは無効なバイト列を含む可能性があり、無効なバイト列を受け取ったときのデシリアライザの動作は実際の実装に依存します。
- デシリアライザは、アプリケーションがオブジェクトをどのように扱うかを決定できるように、元のバイト配列を取得する機能を提供すべきです。
-
Arrayオブジェクトの最大要素数は
(2^32)-1
です。 -
Mapオブジェクトのキーと値の関連付けの最大数は
(2^32)-1
です。
拡張タイプ
MessagePackでは、Extension型を使用してアプリケーション固有のタイプを定義できます。
拡張タイプは整数とバイト配列で構成され、整数は型の種類を、バイト配列はデータを表します。
アプリケーションは、アプリケーション固有の型情報を0
から127
に割り当てることが出来ます。使い方の例として、アプリケーションが type = 0
をアプリケーション独自の型システムとして定義し、ペイロードに型の名前と型の値を格納します。
MessagePack は -1
から -128
を将来の拡張のために予約し、定義済みの型を追加します。これらの型は、異なるプログラミング環境間で事前に共有された静的に型付けされたスキーマを使用することなく、より多くの型を交換するために追加される予定です。
0 - 127: アプリケーション固有の型
-128 - -1: 定義済み型のために予約されている。
拡張型は追加されることを意図しているため、古いアプリケーションはそのすべてを実装していないかもしれません。しかし、そのような型でも拡張型の1つとして扱うことができます。そのため、アプリケーションは未知のExtension型を拒否するか、不透明なデータとして受け入れるか、ペイロードに触れずに他のアプリケーションに転送するかを決定することができます。
以下は、定義済みの拡張タイプのリストです。これらの型のフォーマットは、フォーマットセクションで定義されています。
名前 | 型 |
---|---|
Timestamp | -1 |
フォーマット
概要
フォーマット名 | 先頭バイト (2進数) | 先頭バイト (16進数) |
---|---|---|
positive fixint |
0xxxxxxx | 0x00 - 0x7f |
fixmap |
1000xxxx | 0x80 - 0x8f |
fixarray |
1001xxxx | 0x90 - 0x9f |
fixstr |
101xxxxx | 0xa0 - 0xbf |
nil |
11000000 | 0xc0 |
(利用不可) | 11000001 | 0xc1 |
false |
11000010 | 0xc2 |
true |
11000011 | 0xc3 |
bin 8 |
11000100 | 0xc4 |
bin 16 |
11000101 | 0xc5 |
bin 32 |
11000110 | 0xc6 |
ext 8 |
11000111 | 0xc7 |
ext 16 |
11001000 | 0xc8 |
ext 32 |
11001001 | 0xc9 |
float 32 |
11001010 | 0xca |
float 64 |
11001011 | 0xcb |
uint 8 |
11001100 | 0xcc |
uint 16 |
11001101 | 0xcd |
uint 32 |
11001110 | 0xce |
uint 64 |
11001111 | 0xcf |
int 8 |
11010000 | 0xd0 |
int 16 |
11010001 | 0xd1 |
int 32 |
11010010 | 0xd2 |
int 64 |
11010011 | 0xd3 |
fixext 1 |
11010100 | 0xd4 |
fixext 2 |
11010101 | 0xd5 |
fixext 4 |
11010110 | 0xd6 |
fixext 8 |
11010111 | 0xd7 |
fixext 16 |
11011000 | 0xd8 |
str 8 |
11011001 | 0xd9 |
str 16 |
11011010 | 0xda |
str 32 |
11011011 | 0xdb |
array 16 |
11011100 | 0xdc |
array 32 |
11011101 | 0xdd |
map 16 |
11011110 | 0xde |
map 32 |
11011111 | 0xdf |
negative fixint |
111xxxxx | 0xe0 - 0xff |
図の表記法
1バイト:
+--------+
| |
+--------+
可変長のバイト:
+========+
| |
+========+
可変長の、MessagePack形式で保存されるオブジェクト:
+~~~~~~~~~~~~~~~~~+
| |
+~~~~~~~~~~~~~~~~~+
X
、Y
、Z
、A
は実際のビットに置き換えられる記号です。
nil
nil
は1バイトにnilを格納します。
+--------+
| 0xc0 |
+--------+
boolフォーマットファミリ
boolフォーマットファミリは、1バイトにfalse
またはtrue
を格納します。
false
+--------+
| 0xc2 |
+--------+
true
+--------+
| 0xc3 |
+--------+
intフォーマットファミリ
intフォーマットファミリは整数を1、2、3、5、または9バイトで格納します。
positive fixint
positive fixint
は 7 ビットの正の整数を格納します
0XXXXXXX
は8ビット符号なし整数です。
+--------+
|0XXXXXXX|
+--------+
negative fixint
negative fixint
は5ビットの負の整数を格納します。
111YYYY
は8ビット符号付き整数です。
+--------+
|111YYYYY|
+--------+
uint 8
uint 8
は8ビット符号なし整数を格納します。
+--------+--------+
| 0xcc |ZZZZZZZZ|
+--------+--------+
uint 16
uint 16
は16ビットのビッグエンディアン符号なし整数を格納します。
+--------+--------+--------+
| 0xcd |ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+
uint 32
uint 32
は32ビットのビッグエンディアン符号なし整数を格納します。
+--------+--------+--------+--------+--------+
| 0xce |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+
uint 64
uint 64
は64ビットのビッグエンディアン符号なし整数を格納します。
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xcf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
int 8
int 8
は8ビットの符号付き整数を格納します。
+--------+--------+
| 0xd0 |ZZZZZZZZ|
+--------+--------+
int 16
int 16
は16ビットのビッグエンディアン符号付き整数を格納します。
+--------+--------+--------+
| 0xd1 |ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+
int 32
int 32
は32ビットのビッグエンディアン符号付き整数を格納します。
+--------+--------+--------+--------+--------+
| 0xd2 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+
int 64
int 64
は64ビットのビッグエンディアン符号付き整数を格納します。
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xd3 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
floatフォーマットファミリ
floatフォーマットファミリは、浮動小数点数を5バイトまたは9バイトで格納します。
float 32
float 32
は、IEEE 754単精度浮動小数点数フォーマットで浮動小数点数を格納します。
XXXXXXXX_XXXXXXXX_XXXXXXXX
はビッグエンディアンのIEEE 754単精度浮動小数点数です。単精度から倍精度に精度を拡張しても精度は落ちません。
+--------+--------+--------+--------+--------+
| 0xca |XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX|
+--------+--------+--------+--------+--------+
float 64
float 64
は、IEEE 754倍精度浮動小数点数フォーマットで浮動小数点数を格納します。
YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY_YYYYYYYY
はビッグエンディアンのIEEE 754倍精度浮動小数点数です。
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xcb |YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|YYYYYYYY|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
strフォーマットファミリ
strフォーマットファミリは、バイト配列のサイズに加えて、1、2、3、または5バイトの追加バイトでバイト配列を格納します。
fixstr
fixstr
は、最大31バイトのバイト配列を格納します。
XXXXX
は5ビットの符号なし整数で、データの長さを表します。
+--------+========+
|101XXXXX| data |
+--------+========+
str 8
str 8
は、最大(2^8)-1
バイト(256バイト未満)のバイト配列を格納します。
YYYYYYY
は8ビットの符号なし整数で、データの長さを表します。
+--------+--------+========+
| 0xd9 |YYYYYYYY| data |
+--------+--------+========+
str 16
str 16
は、最大(2^16)-1
バイト(64kB未満)のバイト配列を格納します。
ZZZZZZ_ZZZZZZZZ
は16ビットのビッグエンディアン符号なし整数で、データの長さを表します。
+--------+--------+--------+========+
| 0xda |ZZZZZZZZ|ZZZZZZZZ| data |
+--------+--------+--------+========+
str 32
str 32
は、最大(2^32)-1
バイト(4GB未満)のバイト配列を格納します。
AAAAAAAAAA_AAAAAAAA_AAAAAAAA
は32ビットのビッグエンディアン符号なし整数で、データの長さを表します。
+--------+--------+--------+--------+--------+========+
| 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data |
+--------+--------+--------+--------+--------+========+
binフォーマットファミリ
binフォーマットファミリは、バイト配列のサイズに加えて、2バイト、3バイト、または5バイトの余分なバイトでバイト配列を格納します。
bin 8
bin 8
は、最大(2^8)-1
バイトのバイト配列を格納します。
XXXXXXXX
はデータの長さを表す8ビットの符号なし整数です。
+--------+--------+========+
| 0xc4 |XXXXXXXX| data |
+--------+--------+========+
bin 16
bin 16
は、最大(2^16)-1
バイトのバイト配列を格納します。
YYYYYYY_YYYYYYY
はデータの長さを表す16ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+========+
| 0xc5 |YYYYYYYY|YYYYYYYY| data |
+--------+--------+--------+========+
bin 32
bin 32
は、最大(2^32)-1
バイトのバイト配列を格納します。
ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ
はデータの長さを表す32ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+--------+--------+========+
| 0xc6 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| data |
+--------+--------+--------+--------+--------+========+
arrayフォーマットファミリ
arrayフォーマットファミリは、要素に加えて1、3、または5バイトの余分なバイトに要素のシーケンスを格納します。
fixarray
fixarray
は、最大15要素の配列を格納します。
XXXX
は配列のサイズ(N
)を表す4ビットの符号なし整数です。
+--------+~~~~~~~~~~~~~~~~~+
|1001XXXX| N objects |
+--------+~~~~~~~~~~~~~~~~~+
array 16
array 16
は、最大(2^16)-1
要素の長さの配列を格納します。
YYYYYY_YYYYYYY
は配列のサイズ(N
)を表す16ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xdc |YYYYYYYY|YYYYYYYY| N objects |
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
array 32
array 32
は、最大(2^32)-1
要素の長さの配列を格納します。
ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ
は配列のサイズ(N
)を表す32ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xdd |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N objects |
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
mapフォーマットファミリ
mapフォーマットファミリは、キーと値のペアのシーケンスに加え、1、3、または5バイトの余分なバイトを格納します。
オブジェクトの奇数要素はマップのキーで、キーの次の要素に対応する値が格納されます。
fixmap
fixmap
は、15要素までの長さのマップを格納します。
XXXX
はマップのサイズ(N
)を表す4ビットの符号なし整数です。
+--------+~~~~~~~~~~~~~~~~~+
|1000XXXX| N*2 objects |
+--------+~~~~~~~~~~~~~~~~~+
map 16
map 16
は、(2^16)-1要素までの長さのマップを格納します。
YYYYYYY_YYYYYYY
はマップのサイズ(N
)を表す16ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xde |YYYYYYYY|YYYYYYYY| N*2 objects |
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
map 32
map 32
は、(2^32)-1要素までの長さのマップを格納します。
ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ
はマップのサイズ(N
)を表す32ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
| 0xdf |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| N*2 objects |
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
extフォーマットファミリ
extフォーマットファミリは、整数とバイト配列のタプルを格納します。
fixext 1
fixext 1
は、整数と1バイトのバイト配列を格納します。
+--------+--------+--------+
| 0xd4 | type | data |
+--------+--------+--------+
fixext 2
fixext 2
は、整数と2バイトのバイト配列を格納します。
+--------+--------+--------+--------+
| 0xd5 | type | data |
+--------+--------+--------+--------+
fixext 4
fixext 4
は、整数と4バイトのバイト配列が格納します。
+--------+--------+--------+--------+--------+--------+
| 0xd6 | type | data |
+--------+--------+--------+--------+--------+--------+
fixext 8
fixext 8
は、整数と8バイトのバイト配列を格納します。
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xd7 | type | data |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
fixext 16
fixext 16
は、整数と16バイトのバイト配列を格納します。
--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 0xd8 | type | data
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+--------+--------+--------+--------+--------+--------+--------+--------+
data |
+--------+--------+--------+--------+--------+--------+--------+--------+
ext 8
ext 8
は、整数と、長さが最大(2^8)-1
バイトまでのバイト配列を格納します。
XXXXXXXX
はデータの長さ(N
)を表す8ビットの符号なし整数です。
+--------+--------+--------+========+
| 0xc7 |XXXXXXXX| type | data |
+--------+--------+--------+========+
ext 16
ext 16
は、整数と、長さが最大(2^16)-1
バイトまでのバイト配列を格納します。
YYYYYYY_YYYYYYYY
はデータの長さ(N
)を表す16ビットのビッグエンディアン符号なし整数です。
+--------+--------+--------+--------+========+
| 0xc8 |YYYYYYYY|YYYYYYYY| type | data |
+--------+--------+--------+--------+========+
ext 32
ext 32
は、整数と、長さが最大(2^32)-1
バイトまでのバイト配列を格納します。
ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ
はデータの長さ(N
)を表すビッグエンディアンの32ビット符号なし整数です。
+--------+--------+--------+--------+--------+--------+========+
| 0xc9 |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ| type | data |
+--------+--------+--------+--------+--------+--------+========+
- typeは符号付き8ビット整数です。
- 負のtypeは2バイトの型情報であり、将来の拡張のために予約されています。
timestamp
timestamp
は、拡張タイプ-1に割り当てられています。32ビット形式、64ビット形式、96ビット形式があります。
timestamp 32
timestamp 32
は1970-01-01 00:00:00UTC
からの経過秒数をを32ビットの符号なし整数に格納します
timestamp 32
は1970-01-01 00:00:00 UTC
から2106-02-07 06:28:16 UTC
まで範囲のタイムスタンプを表すことができます。ナノ秒の部分は0です。
+--------+--------+--------+--------+--------+--------+
| 0xd6 | -1 | seconds in 32-bit unsigned int |
+--------+--------+--------+--------+--------+--------+
timestamp 64
timestamp 64
は1970-01-01 00:00:00 UTC
からの経過秒数とナノ秒数を64ビットの符号なし整数に格納します
timestamp 64
は1970-01-01 00:00:00.000000000 UTC
から2514-05-30 01:53:04.000000000 UTC
まで範囲のタイムスタンプを表すことができます。
+--------+--------+--------+--------+--------+------|-+--------+--------+--------+--------+
| 0xd7 | -1 | nanosec. in 30-bit unsigned int | seconds in 34-bit unsigned int |
+--------+--------+--------+--------+--------+------^-+--------+--------+--------+--------+
timestamp 96
timestamp 96
は1970-01-01 00:00:00 UTC
からの経過秒数とナノ秒数を64ビット符号付き整数と32ビット符号なし整数に格納します
timestamp 96
は-292277022657-01-27 08:29:52 UTC
から292277026596-12-04 15:30:08.000000000 UTC
まで範囲のタイムスタンプを表すことができます。
+--------+--------+--------+--------+--------+--------+--------+
| 0xc7 | 12 | -1 |nanoseconds in 32-bit unsigned int |
+--------+--------+--------+--------+--------+--------+--------+
+--------+--------+--------+--------+--------+--------+--------+--------+
seconds in 64-bit signed int |
+--------+--------+--------+--------+--------+--------+--------+--------+
-
timestamp 64
およびtimestamp 96
フォーマットでは、ナノ秒は最大9999999です。
シリアライズの疑似コード
struct timespec {
long tv_sec; // seconds
long tv_nsec; // nanoseconds
} time;
if ((time.tv_sec >> 34) == 0) {
uint64_t data64 = (time.tv_nsec << 34) | time.tv_sec;
if (data64 & 0xffffffff00000000L == 0) {
// timestamp 32
uint32_t data32 = data64;
serialize(0xd6, -1, data32)
}
else {
// timestamp 64
serialize(0xd7, -1, data64)
}
}
else {
// timestamp 96
serialize(0xc7, 12, -1, time.tv_nsec, time.tv_sec)
}
デシリアライズの疑似コード
ExtensionValue value = deserialize_ext_type();
struct timespec result;
switch(value.length) {
case 4:
uint32_t data32 = value.payload;
result.tv_nsec = 0;
result.tv_sec = data32;
case 8:
uint64_t data64 = value.payload;
result.tv_nsec = data64 >> 34;
result.tv_sec = data64 & 0x00000003ffffffffL;
case 12:
uint32_t data32 = value.payload;
uint64_t data64 = value.payload + 4;
result.tv_nsec = data32;
result.tv_sec = data64;
default:
// error
}
シリアライズ: 型からフォーマットへの変換
MessagePackシリアライザは、MessagePack型を以下のようなフォーマットに変換します。
入力型 | 出力フォーマット |
---|---|
Integer |
intフォーマットファミリ (positive fixint , negative fixint , int 8/16/32/64 または uint 8/16/32/64 ) |
Nil | nil |
Boolean |
boolフォーマットファミリ (false またはtrue ) |
Float |
floatフォーマットファミリ (float 32/64 ) |
String |
strフォーマットファミリ (fixstr またはstr 8/16/32 ) |
Binary |
binフォーマットファミリ (bin 8/16/32 ) |
Array |
arrayフォーマットファミリ (fixarray またはarray 16/32 ) |
Map |
mapフォーマットファミリ (fixmap またはmap 16/32 ) |
Extension |
extフォーマットファミリ (fixext またはext 8/16/32 ) |
オブジェクトが複数の出力フォーマットで表現できる場合、シリアライザーは最小のバイト数でデータを表現するフォーマットを使用すべきです(SHOULD)。
デシリアライズ: フォーマットから型への変換
MessagePackデシリアライザは MessagePackのフォーマットを以下のような型に変換します。
入力フォーマット | 出力型 |
---|---|
positive fixint , negative fixint , int 8/16/32/64 または uint 8/16/32/64
|
Integer |
nil |
Nil |
false またはtrue
|
Boolean |
float 32/64 |
Float |
fixstr またはstr 8/16/32
|
String |
bin 8/16/32 |
Binary |
fixarray またはarray 16/32
|
Array |
fixmap またはmap 16/32
|
Map |
fixext またはext 8/16/32
|
Extension |
将来の議論
プロファイル
プロファイルとは、MessagePackを特定のユースケースに適応させるために、同じシンタックスを共有しながら、アプリケーションによって MessagePack のセマンティクスを制限するアイデアです。
例えば、アプリケーションはBinary型を削除し、mapオブジェクトのキーをString型に制限し、JSONとセマンティクスを互換にするためにいくつかの制限を加えることができます。スキーマを使用するアプリケーションでは、String型とBinary型を削除し、Raw型としてバイト配列を扱うことができます。直列化されたデータのハッシュ(ダイジェスト)を使用するアプリケーションは、直列化されたデータを確定的にするために、マップのキーをソートすることができる。
実装ガイドライン
MessagePack 仕様のアップグレード
現在、MessagePackの仕様が変更されています。
以下は既存のMessagePack実装をアップグレードするためのガイドラインです。
- マイナーリリースでは、デシリアライザはbinフォーマットファミリーと
str 8
フォーマットをサポートします。デシリアライズされるオブジェクトの型はraw 16
(==str 16
) またはraw 32
(==str 32
) と同じでなければなりません。 - メジャーリリースでは、デシリアライザはbinフォーマットファミリーとstrフォーマットファミリーを使用してBinary型とString型を区別します。
- 同時に、シリアライザはbinフォーマットファミリーと
str 8
フォーマットを使用しない "互換モード"を提供すべきである。
- 同時に、シリアライザはbinフォーマットファミリーと