Модуль yaml
Модуль yaml принимает строки в формате YAML и
декодирует их, либо принимает набор значений произвольного формата и
кодирует их в YAML.
Ниже приведен перечень всех функций и элементов модуля yaml.
Имя | Назначение |
|---|---|
Преобразование Lua-объекта в YAML-строку | |
Преобразование YAML-строки в Lua-объект | |
Задание структуры вывода | |
Изменение конфигурации | |
Аналог значения "nil" в Lua |
Конвертация Lua-объекта в YAML-строку.
Параметры:
lua-value— скалярное значение или значение таблицы Lua.
Возвращает
исходное значение, переформатированное в YAML-строку.
Тип возвращаемого значения
string
Конвертация YAML-строки в Lua-объект.
Параметры:
string— строка в формате YAML.
Возвращает
исходное содержимое, отформатированное как таблица Lua.
Тип возвращаемого значения
table
Задание структуры вывода.
Структуру вывода 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"). Полный пример приведен в разделе «Пример»
ниже.
Задание значений, влияющих на поведение функций encode и decode.
Все значения являются целыми числами или логическими true/false.
Параметр | По умолчанию | Назначение |
|---|---|---|
| true | Флаг, указывающий, включать ли кодирование чисел NaN и Inf |
| 14 | Точность чисел с плавающей запятой |
| true | Флаг, указывающий, будет ли сериализатор следовать полю метатаблицы __serialize |
| false | Флаг, указывающий, использовать ли |
| false | Флаг, указывающий, использовать ли NULL для нераспознанных типов |
| true | Флаг, указывающий, следует ли обрабатывать чрезмерно разреженные массивы как отображения (map). Подробное описание см. ниже |
| 2 | 1/ |
| 10 | Ограничение, гарантирующее, что небольшие массивы Lua всегда кодируются как разреженные массивы (вместо генерации ошибки или кодирования как отображения) |
| true | Флаг, указывающий, включать ли декодирование чисел NaN и Inf |
| 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: b1: 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: b1: a......
При кодировании YAML-кодер пытается классифицировать таблицу по одному из четырёх типов:
- Отображение (map): хотя бы один индекс таблицы не является беззнаковым целым числом.
- Обычный массив: все индексы массива доступны.
- Разреженный массив: хотя бы один индекс массива пропущен.
- Чрезмерно разреженный массив: количество пропущенных значений превышает заданный коэффициент.
Массив считается чрезмерно разреженным, если выполняются все следующие условия:
encode_sparse_ratio> 0max(table)>encode_sparse_safemax(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.
Значение, сопоставимое с нулевым значением "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: A2: 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: Bf1: A......