Tarantool CE/EE Documentation portal logo
Помощь
Обновлена 15 сентября 2026 г. в 08:55

Модуль msgpack

Общие сведения

Модуль msgpack декодирует сырые строки MsgPack, преобразуя их в объекты Lua, и кодирует объекты Lua, преобразуя их в сырые строки MsgPack. Tarantool активно использует MsgPack внутри системы, поскольку кортежи в Tarantool хранятся в виде массивов MsgPack.

Кроме того, начиная с версии 2.10.0, с помощью модуля msgpack можно создавать специальный объект Lua типа userdata — объект MsgPack. Объект MsgPack хранит произвольные данные MsgPack и может быть создан из любого объекта Lua, включая другой объект MsgPack, а также из сырой строки MsgPack. У объекта MsgPack есть собственный набор методов и итераторов.

Определения

Справочник по API

Ниже приведен список членов msgpack и связанных объектов.

Элементы

Связанные объекты

msgpack.encode(lua_value)

Преобразует объект Lua в строку в формате MsgPack.

Параметры:

  • lua_value — скалярное значение или значение таблицы Lua.

Возвращает

исходное содержимое в формате строки MsgPack;

Тип возвращаемого значения

строка MsgPack

msgpack.encode(lua_value, ibuf)

Преобразует объект Lua в строку MsgPack в ibuf — буфере, создаваемом функцией buffer.ibuf(). Как и в случае с msgpack.encode(lua_value), результат представляет собой строку MsgPack, но записывается в выходной буфер ibuf вместо возврата.

Параметры:

  • lua_value (lua-object) — скалярное значение или значение таблицы Lua.
  • ibuf (buffer) — (выходной параметр) куда записывается результирующая строка MsgPack

Возвращает

количество байтов в выходных данных

Тип возвращаемого значения

строка MsgPack

Пример использования buffer.ibuf(), ffi.string() и string.hex():

ibuf = require('buffer').ibuf()msgpack_string_size = require('msgpack').encode({'a'}, ibuf)msgpack_string = require('ffi').string(ibuf.rpos, msgpack_string_size)string.hex(msgpack_string)

Результат: '91a161', так как 91 — это кодировка MessagePack для «fixarray size 1», a1 — кодировка MessagePack для «fixstr size 1», а 61 — кодировка UTF-8 символа 'a'.

msgpack.decode(msgpack_string [, start_position])

Преобразует строку MsgPack в объект Lua.

Параметры:

  • msgpack_string (string) — строка MsgPack.
  • start_position (integer) — позиция начала, минимум = 1, максимум = длина строки, по умолчанию = 1.

Возвращает

  • (если msgpack_string — корректная строка MsgPack) исходное содержимое msgpack_string в формате объекта Lua, обычно таблицы Lua; (в противном случае) скалярное значение, например строка или число;
  • "next_start_position". Если decode останавливается после разбора до байта N в msgpack_string, то "next_start_position" будет равно N + 1, и decode(msgpack_string, next_start_position) продолжит разбор с того места, где остановился предыдущий вызов decode, плюс 1. Обычно decode разбирает всю строку msgpack_string, поэтому "next_start_position" будет равно string.len(msgpack_string) + 1.

Тип возвращаемого значения

объект Lua и число

Пример: результат: ['a'] и 4:

msgpack_string = require('msgpack').encode({'a'})require('msgpack').decode(msgpack_string, 1)

msgpack.decode(C_style_string_pointer, size)

Преобразует строку MsgPack, адрес которой передан в виде указателя на строку в стиле C (например, указателя rpos внутри ibuf, создаваемого функцией buffer.ibuf()), в объект Lua. Указатель на строку в стиле C может быть описан как cdata<char *> или cdata<const char *>.

Параметры:

  • C_style_string_pointer (buffer) — указатель на строку MsgPack.
  • size (integer) — количество байтов в строке MsgPack

Возвращает

  • (если C_style_string_pointer указывает на корректную строку MsgPack) исходное содержимое msgpack_string в формате объекта Lua, обычно таблицы Lua; (в противном случае) скалярное значение, например строка или число;
  • returned_pointer = указатель в стиле C на байт после переданных данных, так что C_style_string_pointer + size = returned_pointer

Тип возвращаемого значения

таблица и указатель в стиле C на позицию после переданных данных

Пример: пример использования buffer.ibuf и арифметики указателей. Результат: ['a'], 3 и true:

ibuf = require('buffer').ibuf()msgpack_string_size = require('msgpack').encode({'a'}, ibuf)a, b = require('msgpack').decode(ibuf.rpos, msgpack_string_size)a, b - ibuf.rpos, msgpack_string_size == b - ibuf.rpos

msgpack.decode_unchecked(msgpack_string [, start_position])

Входные и выходные данные те же, что и для msgpack.decode(string).

msgpack.decode_unchecked(C_style_string_pointer)

Входные и выходные данные те же, что и для msgpack.decode(C_style_string_pointer), за исключением того, что size не требуется. Часть проверок пропускается, и decode_unchecked(C_style_string_pointer) может работать с указателями на строки в буферах, которые decode(C_style_string_pointer) не может обработать. Пример см. в модуле buffer.

msgpack.decode_array_header(byte-array, size)

Вызывает функцию mp_decode_array из библиотеки MsgPuck и возвращает размер массива и указатель на первый элемент массива. Последующий вызов msgpack_decode может декодировать отдельный элемент вместо всего массива.

Параметры:

  • byte-array — указатель на строку MsgPack.
  • size — число, большее или равное длине строки

Возвращает

  • размер массива;
  • указатель на позицию после заголовка массива.

Пример:

-- Example of decode_array_header-- Suppose we have the raw data '\x93\x01\x02\x03'.-- \x93 is MsgPack encoding for a header of a three-item array.-- We want to skip it and decode the next three items.msgpack = require('msgpack');ffi = require('ffi');x, y = msgpack.decode_array_header(ffi.cast('char*', '\x93\x01\x02\x03'), 4)a = msgpack.decode(y, 1);b = msgpack.decode(y + 1, 1);c = msgpack.decode(y + 2, 1);a, b, c-- The result is: 1,2,3.

msgpack.decode_map_header(byte-array, size)

Вызывает функцию mp_decode_map из библиотеки MsgPuck и возвращает размер карты и указатель на первый элемент карты. Последующий вызов msgpack_decode может декодировать отдельный элемент вместо всей карты.

Параметры:

  • byte-array — указатель на строку MsgPack.
  • size — число, большее или равное длине строки MsgPack

Возвращает

  • размер карты;
  • указатель на позицию после заголовка карты.

Пример:

-- Example of decode_map_header-- Suppose we have the raw data '\x81\xa2\x41\x41\xc3'.-- '\x81' is MsgPack encoding for a header of a one-item map.-- We want to skip it and decode the next map item.msgpack = require('msgpack');ffi = require('ffi')x, y = msgpack.decode_map_header(ffi.cast('char*', '\x81\xa2\x41\x41\xc3'), 5)a = msgpack.decode(y, 3);b = msgpack.decode(y + 3, 1)x, a, b-- The result is: 1,"AA", true.

Параметр __serialize

Структура вывода MsgPack может быть задана с помощью параметра __serialize:

  • 'seq', 'sequence', 'array' — таблица кодируется как массив
  • 'map', 'mapping' — таблица кодируется как карта
  • function — метаметод, вызываемый для получения сериализуемого представления таблиц, объектов cdata или userdata

Сериализация 'A' и 'B' с разными значениями __serialize дает разные результаты. Чтобы продемонстрировать это, ниже приведена процедура, которая кодирует {'A','B'} и как массив, и как карту, а затем отображает каждый результат в шестнадцатеричном формате.

function hexdump(bytes)    local result = ''    for i = 1, #bytes do        result = result .. string.format("%x", string.byte(bytes, i)) .. ' '    end    return resultendmsgpack = require('msgpack')m1 = msgpack.encode(setmetatable({'A', 'B'}, {                             __serialize = "seq"                          }))m2 = msgpack.encode(setmetatable({'A', 'B'}, {                             __serialize = "map"                          }))print('array encoding: ', hexdump(m1))print('map encoding: ', hexdump(m2))

Результат:

array encoding: 92 a1 41 a1 42map encoding:   82 01 a1 41 02 a1 42

На странице спецификации MsgPack указано, что первая кодировка означает:

fixarray(2), fixstr(1), "A", fixstr(1), "B"

а значение второго результата кодирования:

fixmap(2), key(1), fixstr(1), "A", key(2), fixstr(2), "B"

Стандартные типы и кодировки MsgPack

Ниже приведены примеры всех стандартных типов: слева отображение в Lua-таблице, а справа – имя и кодировка в формате MsgPack.

{}

'fixmap' = 80, если метатаблица 'map', иначе 'fixarray' = 90

'a'

'fixstr' = a1 61

false

'false' = c2

true

'true' = c3

127

'positive fixint' = 7f

65535

'uint 16' = cd ff ff

4294967295

'uint 32' = ce ff ff ff ff

nil

'nil' = c0

msgpack.NULL

то же, что nil

[0] = 5

'fixmap(1)' + 'positive fixint' (для ключа) + 'positive fixint' (для значения) = 81 00 05

[0] = nil

'fixmap(0)' = 80 – nil не сохраняется, если это отсутствующее значение карты

1.5

'float 64' = cb 3f f8 00 00 00 00 00 00

msgpack.cfg(table)

Изменяет параметры конфигурации MsgPack.

Все значения — целые числа или логические true/false.

Параметр

По умолчанию

Назначение

cfg.encode_max_depth

128

Максимальная глубина рекурсии при кодировании

cfg.encode_deep_as_nil

false

Определяет, следует ли обрезать таблицы с уровнем вложенности выше cfg.encode_max_depth. Незакодированные поля заменяются одним значением null. Если не задано, слишком высокая вложенность считается ошибкой.

cfg.encode_invalid_numbers

true

Определяет, следует ли включить кодирование чисел NaN и Inf

cfg.encode_load_metatables

true

Определяет, будет ли сериализатор следовать полю метатаблицы __serialize

cfg.encode_use_tostring

false

Определяет, следует ли использовать tostring() для неизвестных типов

cfg.encode_invalid_as_nil

false

Определяет, следует ли использовать NULL для нераспознанных типов

cfg.encode_sparse_convert

true

Определяет, следует ли обрабатывать избыточно разреженные массивы как карты. Подробное описание см. ниже

cfg.encode_sparse_ratio

2

1/encode_sparse_ratio — допустимая доля пропущенных значений в разреженном массиве

cfg.encode_sparse_safe

10

Ограничение, гарантирующее, что небольшие массивы Lua всегда кодируются как разреженные массивы (вместо генерации ошибки или кодирования в виде карты)

cfg.encode_error_as_ext

true

Определяет, как объекты ошибок (box.error.new()) кодируются в формате MsgPack: если true, ошибки кодируются как расширение MsgPack MP_ERROR; если false, формат кодирования зависит от других параметров конфигурации (encode_load_metatables, encode_use_tostring, encode_invalid_as_nil).

cfg.decode_invalid_numbers

true

Определяет, следует ли включить декодирование чисел NaN и Inf

cfg.decode_save_metatables

true

Определяет, следует ли устанавливать метатаблицы для всех массивов и карт

Особенности разреженных массивов

При кодировании кодировщик MsgPack пытается классифицировать таблицы по одному из четырех типов:

  • map (карта) — хотя бы один индекс таблицы не является беззнаковым целым числом
  • regular array (обычный массив) — все индексы массива доступны
  • sparse array (разреженный массив) — хотя бы один индекс массива отсутствует
  • excessively sparse array (избыточно разреженный массив) — количество пропущенных значений превышает заданное соотношение

Массив считается избыточно разреженным, если выполняются все следующие условия:

  • encode_sparse_ratio > 0
  • max(table) > encode_sparse_safe
  • max(table) > count(table) * encode_sparse_ratio

Кодировщик MsgPack никогда не считает массив избыточно разреженным при encode_sparse_ratio = 0. Ограничение encode_sparse_safe гарантирует, что небольшие массивы Lua всегда кодируются как разреженные массивы. По умолчанию попытка кодирования избыточно разреженного массива вызывает ошибку. Если параметр encode_sparse_convert установлен в значение true, избыточно разреженные массивы обрабатываются как карты.

Пример 1 использования msgpack.cfg():

Если msgpack.cfg.encode_invalid_numbers = true (по умолчанию), то NaN и Inf являются допустимыми значениями. Если это нежелательно, можно запретить msgpack.encode() принимать их, задав msgpack.cfg{encode_invalid_numbers = false}, таким образом:

tarantool> msgpack = require('msgpack'); msgpack.cfg{encode_invalid_numbers = true}---tarantool> msgpack.decode(msgpack.encode{1, 0 / 0, 1 / 0, false})---- [1, -nan, inf, false]- 22tarantool> msgpack.cfg{encode_invalid_numbers = false}---tarantool> msgpack.decode(msgpack.encode{1, 0 / 0, 1 / 0, false})---- error: ... number must not be NaN or Inf'

Пример 2: msgpack.cfg():

Чтобы избежать ошибок при попытках закодировать неизвестные типы данных как userdata/cdata, можно использовать следующий код:

tarantool> httpc = require('http.client').new()---tarantool> msgpack.encode(httpc.curl)---- error: unsupported Lua type 'userdata'tarantool> msgpack.cfg{encode_use_tostring = true}---tarantool> msgpack.encode(httpc.curl)---- !!binary tnVzZXJkYXRhOiAweDAxMDU5NDQ2Mzg=

Аналогичные параметры конфигурации существуют для JSON и YAML.

msgpack.NULL

Значение, сопоставимое с нулевым значением "nil" в языке Lua, которое можно использовать в качестве объекта-заполнителя в кортеже.

Пример:

tarantool> msgpack = require('msgpack')---tarantool> y = msgpack.encode({'a',1,'b',2})---tarantool> z = msgpack.decode(y)---tarantool> z[1], z[2], z[3], z[4]---- a- 1- b- 2tarantool> box.space.tester:insert{20, msgpack.NULL, 20}---- [20, null, 20]

msgpack.object(lua_value)

Начиная с: 2.10.0

Кодирует произвольный объект Lua в формат MsgPack.

Параметры:

  • lua_value (lua-object) — объект Lua любого типа.

Возвращает

закодированные данные MsgPack, инкапсулированные в объект MsgPack.

Тип возвращаемого значения

userdata

Пример:

local msgpack = require('msgpack')-- Create a MsgPack object from a Lua object of any typelocal mp_from_number = msgpack.object(123)local mp_from_string = msgpack.object('hello world')local mp_from_array = msgpack.object({ 10, 20, 30 })local mp_from_table = msgpack.object({ band_name = 'The Beatles', year = 1960 })local mp_from_tuple = msgpack.object(box.tuple.new{1, 'The Beatles', 1960})

msgpack.object_from_raw(msgpack_string)

Начиная с: 2.10.0

Создает объект MsgPack из сырой строки MsgPack.

Параметры:

  • msgpack_string (string) — сырая строка MsgPack.

Возвращает

объект MsgPack

Тип возвращаемого значения

userdata

Пример:

local msgpack = require('msgpack')-- Create a MsgPack object from a raw MsgPack stringlocal raw_mp_string = msgpack.encode({ 10, 20, 30 })local mp_from_mp_string = msgpack.object_from_raw(raw_mp_string)

msgpack.object_from_raw(C_style_string_pointer, size)

Начиная с: 2.10.0

Создает объект MsgPack из сырой строки MsgPack. Адрес строки MsgPack передается как указатель на строку в стиле C, например, как указатель rpos внутри ibuf, создаваемого функцией buffer.ibuf(). Указатель на строку в стиле C может быть описан как cdata<char *> или cdata<const char *>.

Параметры:

  • C_style_string_pointer (buffer) — указатель на сырую строку MsgPack.
  • size (integer) — количество байтов в сырой строке MsgPack.

Возвращает

объект MsgPack

Тип возвращаемого значения

userdata

Пример:

local msgpack = require('msgpack')-- Create a MsgPack object from a raw MsgPack string using bufferlocal buffer = require('buffer')local ibuf = buffer.ibuf()msgpack.encode({ 10, 20, 30 }, ibuf)local mp_from_mp_string_pt = msgpack.object_from_raw(ibuf.buf, ibuf:size())

msgpack.is_object(some_argument)

Начиная с: 2.10.0

Проверяет, является ли переданный аргумент объектом MsgPack.

Параметры:

  • some_argument — любой аргумент.

Возвращает

true, если аргумент является объектом MsgPack; иначе false

Тип возвращаемого значения

boolean

Пример:

local msgpack = require('msgpack')local mp_from_string = msgpack.object('hello world')-- Check if the given argument is a MsgPack objectlocal mp_is_object = msgpack.is_object(mp_from_string) -- Returns truelocal string_is_object = msgpack.is_object('hello world') -- Returns false

Объекты MsgPack

msgpack_object

Объект MsgPack, хранящий произвольные данные MsgPack. Чтобы создать объект MsgPack из объекта или строки Lua, используйте следующие методы:

Если объект MsgPack хранит массив, его можно вставить в спейс базы данных:

box.space.bands:insert(msgpack.object({1, 'The Beatles', 1960}))

msgpack_object:decode()

Начиная с: 2.10.0

Декодирует данные MsgPack в объекте MsgPack.

Возвращает

объект Lua

Тип возвращаемого значения

объект Lua

Пример:

local msgpack = require('msgpack')local mp_from_number = msgpack.object(123)local mp_from_string = msgpack.object('hello world')-- Decode MsgPack datalocal mp_number_decoded = mp_from_number:decode() -- Returns 123local mp_string_decoded = mp_from_string:decode() -- Returns 'hello world'

msgpack_object:iterator()

Начиная с: 2.10.0

Создает итератор для данных MsgPack.

Возвращает

объект-итератор для данных MsgPack

Тип возвращаемого значения

userdata

msgpack_object[key]

Начиная с: 2.11.0

Получает элемент массива MsgPack по указанному ключу индекса. Для получения элемента массива также можно использовать метод msgpack_object:get(key).

Ключ индекса, используемый для получения элемента массива, может быть одним из следующих:

  • если объект MsgPack является массивом, key — целочисленное значение (начиная с 1), указывающее индекс элемента;
  • если объект MsgPack является ассоциативным массивом, key — строковое значение, указывающее ключ элемента. В этом случае обратиться к элементу массива можно также с помощью точечной нотации (msgpack_object.<key>).

Если указанный ключ отсутствует в массиве, msgpack_object[key] возвращает nil.

Пример:

local msgpack = require('msgpack')local mp_from_array = msgpack.object({ 10, 20, 30 })local mp_from_table = msgpack.object({ band_name = 'The Beatles', year = 1960 })local mp_from_tuple = msgpack.object(box.tuple.new{1, 'The Beatles', 1960})-- Get MsgPack data by the specified index or keylocal mp_array_get_by_index = mp_from_array[1] -- Returns 10local mp_table_get_by_key = mp_from_table['band_name'] -- Returns 'The Beatles'local mp_table_get_by_nonexistent_key = mp_from_table['rating'] -- Returns nillocal mp_tuple_get_by_index = mp_from_tuple[3] -- Returns 1960

msgpack_object:get(key)

Начиная с: 2.11.0

Получает элемент массива MsgPack по указанному ключу индекса. Для получения элемента массива также можно использовать индексную нотацию (msgpack_object[key]).

Параметры:

  • key (number/string) — ключ индекса, используемый для получения элемента массива, который может быть одним из следующих:

    • если объект MsgPack является массивом, key — целочисленное значение (начиная с 1), указывающее индекс элемента;
    • если объект MsgPack является ассоциативным массивом, key — строковое значение, указывающее ключ элемента.

Возвращает

элемент массива MsgPack. Если указанный ключ отсутствует в массиве, get возвращает nil.

iterator_object

Итератор по массиву MsgPack.

iterator_object:decode_array_header()

Начиная с: 2.10.0

Декодирует заголовок массива MsgPack под курсором итератора и сдвигает курсор. После вызова этой функции итератор указывает на первый элемент массива или на значение, следующее за массивом, если массив пуст.

Возвращает

количество элементов в массиве

Тип возвращаемого значения

number

Возможные ошибки: вызывает ошибку, если тип значения под курсором итератора не MP_ARRAY.

Пример:

local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header()  -- returns 4local first = mp_array_iterator:decode()              -- returns 10local second = mp_array_iterator:decode()             -- returns 20mp_array_iterator:skip()                              -- returns none, skips 30local fourth = mp_array_iterator:decode()             -- returns 40

iterator_object:decode_map_header()

Начиная с: 2.10.0

Декодирует заголовок карты MsgPack под курсором итератора и сдвигает курсор. После вызова этой функции итератор указывает на первый ключ, хранящийся в карте, или на значение, следующее за картой, если карта пуста.

Возвращает

количество пар ключ-значение в карте

Тип возвращаемого значения

number

Возможные ошибки: вызывает ошибку, если тип значения под курсором итератора не MP_MAP.

Пример:

local msgpack = require('msgpack')local mp_map = msgpack.object({ foo = 123 })local mp_map_iterator = mp_map:iterator()local size = mp_map_iterator:decode_map_header() -- returns 1local first = mp_map_iterator:decode()           -- returns 'foo'local second = mp_map_iterator:decode()          -- returns '123'

iterator_object:decode()

Начиная с: 2.10.0

Декодирует значение MsgPack под курсором итератора и сдвигает курсор.

Возвращает

объект Lua, соответствующий значению MsgPack

Тип возвращаемого значения

объект Lua

Возможные ошибки: вызывает ошибку Lua, если нет данных для декодирования.

Пример:

local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header()  -- returns 4local first = mp_array_iterator:decode()              -- returns 10local second = mp_array_iterator:decode()             -- returns 20mp_array_iterator:skip()                              -- returns none, skips 30local fourth = mp_array_iterator:decode()             -- returns 40

iterator_object:take()

Начиная с: 2.10.0

Возвращает значение MsgPack под курсором итератора как объект MsgPack без декодирования и сдвигает курсор. Метод не копирует данные MsgPack. Вместо этого он берет ссылку на исходный объект.

Возможные ошибки: вызывает ошибку Lua, если нет данных для декодирования.

Пример:

local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header()  -- returns 3local first = mp_array_iterator:decode()              -- returns 10mp_array_iterator:skip()                              -- returns none, skips 20local mp_value_under_cursor = mp_array_iterator:take()local third = mp_value_under_cursor:decode()          -- returns 30

iterator_object:take_array(count)

Начиная с: 2.10.0

Копирует указанное количество значений MsgPack, начиная с позиции курсора итератора, в новый объект массива MsgPack и сдвигает курсор.

Параметры:

  • count (number) — количество значений MsgPack для копирования

Возвращает

новый объект MsgPack

Возможные ошибки: вызывает ошибку Lua, если недостаточно значений для декодирования. В этом случае позиция курсора итератора не изменяется.

Пример:

local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header()  -- returns 4local first = mp_array_iterator:decode()              -- returns 10local mp_array_new = mp_array_iterator:take_array(2)local mp_array_new_decoded = mp_array_new:decode()    -- returns {20, 30}local fourth = mp_array_iterator:decode()             -- returns 40

iterator_object:skip()

Начиная с: 2.10.0

Сдвигает курсор итератора, пропуская одно значение MsgPack под курсором. Ничего не возвращает.

Возможные ошибки: вызывает ошибку Lua, если нет данных для пропуска.

Пример:

local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header()  -- returns 4local first = mp_array_iterator:decode()              -- returns 10local second = mp_array_iterator:decode()             -- returns 20mp_array_iterator:skip()                              -- returns none, skips 30local fourth = mp_array_iterator:decode()             -- returns 40