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

Модуль yaml

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

Модуль yaml принимает строки в формате YAML и декодирует их, либо принимает набор значений произвольного формата и кодирует их в YAML.

Указатель

Ниже приведен перечень всех функций и элементов модуля yaml.

Имя

Назначение

yaml.encode()

Преобразование Lua-объекта в YAML-строку

yaml.decode()

Преобразование YAML-строки в Lua-объект

__serialize parameter

Задание структуры вывода

yaml.cfg()

Изменение конфигурации

yaml.NULL

Аналог значения "nil" в Lua

yaml.encode(lua-value)

Конвертация Lua-объекта в YAML-строку.

Параметры:

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

Возвращает

исходное значение, переформатированное в YAML-строку.

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

string

yaml.decode(string)

Конвертация YAML-строки в Lua-объект.

Параметры:

  • string — строка в формате YAML.

Возвращает

исходное содержимое, отформатированное как таблица Lua.

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

table

Параметр __serialize

Задание структуры вывода.

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

  • 'seq', 'sequence', 'array': таблица кодируется как массив
  • 'map', 'mapping': таблица кодируется как отображение (map)
  • function: метаметод, вызываемый для распаковки сериализуемого представления таблицы, объектов cdata или userdata
tarantool> yaml.encode(setmetatable({'A', 'B'}, {__serialize='seq'}))---- |  --- ['A', 'B']  ......tarantool> yaml.encode(setmetatable({'A', 'B'}, {__serialize='map'}))---- |  --- {1: 'A', 2: 'B'}  ......

'seq' или 'map' также включают потоковый (компактный) режим для сериализатора YAML (flow="[1,2,3]" вместо block=" - 1\n - 2\n - 3\n"). Полный пример приведен в разделе «Пример» ниже.

yaml.cfg(table)

Задание значений, влияющих на поведение функций encode и decode.

Все значения являются целыми числами или логическими true/false.

Параметр

По умолчанию

Назначение

cfg.encode_invalid_numbers

true

Флаг, указывающий, включать ли кодирование чисел NaN и Inf

cfg.encode_number_precision

14

Точность чисел с плавающей запятой

cfg.encode_load_metatables

true

Флаг, указывающий, будет ли сериализатор следовать полю метатаблицы __serialize

cfg.encode_use_tostring

false

Флаг, указывающий, использовать ли tostring() для неизвестных типов

cfg.encode_invalid_as_nil

false

Флаг, указывающий, использовать ли NULL для нераспознанных типов

cfg.encode_sparse_convert

true

Флаг, указывающий, следует ли обрабатывать чрезмерно разреженные массивы как отображения (map). Подробное описание см. ниже

cfg.encode_sparse_ratio

2

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

cfg.encode_sparse_safe

10

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

cfg.decode_invalid_numbers

true

Флаг, указывающий, включать ли декодирование чисел NaN и Inf

cfg.decode_save_metatables

true

Флаг, указывающий, следует ли задавать метатаблицы для всех массивов и отображений

Примечание о decode_save_metatables

Может потребоваться изменить метатаблицу результата, чтобы получить блочное форматирование encode() для лучшей читаемости, но это следует делать корректно.

Правильный способ — назначить новую метатаблицу.

tarantool> t1 = yaml.decode(yaml.encode({[1] = 'a', x = 'b'}))tarantool> yaml.encode(t1)---- |  --- {'x': 'b', 1: 'a'}  ......tarantool> my_mt = {__serialize = 'mapping'}tarantool> setmetatable(t1, my_mt)tarantool> yaml.encode(t1)---- |  ---  x: b  1: a  ......

Не следует изменять метатаблицу следующим образом.

tarantool> t1 = yaml.decode(yaml.encode({[1] = 'a', x = 'b'}))tarantool> getmetatable(t1).__serialize---- map...tarantool> getmetatable(t1).__serialize = 'mapping' -- (!) badtarantool> t2 = yaml.decode(yaml.encode({[1] = 'a', x = 'b'}))tarantool> yaml.encode(t2) -- (!) got 'block' maps for all results---- |  ---  x: b  1: a  ......

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

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

  • Отображение (map): хотя бы один индекс таблицы не является беззнаковым целым числом.
  • Обычный массив: все индексы массива доступны.
  • Разреженный массив: хотя бы один индекс массива пропущен.
  • Чрезмерно разреженный массив: количество пропущенных значений превышает заданный коэффициент.

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

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

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

Пример yaml.cfg() 1:

Следующий код кодирует 0/0 как NaN («не число») и 1/0 как Inf («бесконечность») вместо возврата nil или сообщения об ошибке:

yaml = require('yaml')yaml.cfg{encode_invalid_numbers = true}x = 0/0y = 1/0yaml.encode({1, x, y, 2})

Результат запроса yaml.encode() будет следующим:

tarantool> yaml.encode({1, x, y, 2})---- '[1,nan,inf,2]'...

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

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

tarantool> httpc = require('http.client').new()---...tarantool> yaml.encode(httpc.curl)---- error: unsupported Lua type 'userdata'...tarantool> yaml.encode(httpc.curl, {encode_use_tostring=true})---- '"userdata: 0x010a4ef2a0"'...

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

yaml.NULL

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

Пример

tarantool> yaml = require('yaml')---...tarantool> y = yaml.encode({'a', 1, 'b', 2})---...tarantool> z = yaml.decode(y)---...tarantool> z[1], z[2], z[3], z[4]---- a- 1- b- 2...tarantool> if yaml.NULL == nil then print('hi') endhi---...

Набор YAML-стилей можно указать с помощью __serialize:

  • __serialize="sequence" или __serialize="array" для массива в формате Block Sequence,
  • __serialize="seq" для массива в формате Flow Sequence,
  • __serialize="mapping" для отображения в формате Block Mapping,
  • __serialize="map" для отображения в формате Flow Mapping.

Сериализация таблиц вида массива или отображения, содержащих 'A' и 'B', с различными значениями __serialize даёт разные результаты:

tarantool> yaml = require('yaml')---...tarantool> yaml.encode(setmetatable({'A', 'B'}, {__serialize='seq'}))---- |  --- ['A', 'B']  ......tarantool> yaml.encode(setmetatable({'A', 'B'}, {__serialize='map'}))---- |  --- {1: 'A', 2: 'B'}  ......tarantool> array_like_table = {'A', 'B'}tarantool> yaml.encode(setmetatable(array_like_table, {__serialize='seq'}))---- |  --- ['A', 'B']  ......tarantool> yaml.encode(setmetatable(array_like_table, {__serialize='sequence'}))tarantool> yaml.encode(setmetatable(array_like_table, {__serialize='array'}))---- |  ---  - A  - B  ......tarantool> yaml.encode(setmetatable(array_like_table, {__serialize='map'}))---- |  --- {1: 'A', 2: 'B'}  ......tarantool> yaml.encode(setmetatable(array_like_table, {__serialize='mapping'}))---- |  ---  1: A  2: B  ......tarantool> map_like_table = {f1 = 'A', f2 = 'B'}tarantool> yaml.encode(setmetatable(map_like_table, {__serialize='seq'}))tarantool> yaml.encode(setmetatable(map_like_table, {__serialize='sequence'}))tarantool> yaml.encode(setmetatable(map_like_table, {__serialize='array'}))---- |  ---  ......tarantool> yaml.encode(setmetatable(map_like_table, {__serialize='map'}))---- |  --- {'f2': 'B', 'f1': 'A'}  ......tarantool> yaml.encode(setmetatable(map_like_table, {__serialize='mapping'}))---- |  ---  f2: B  f1: A  ......