YAML — один из наиболее популярных форматов…
Они сами не знают — форматом чего, на самом деле.
Изначально он был «Yet Another Markup Language» — «Ещё один язык разметки», позже стал «YAML Ain’t Markup Language» — «YAML — не язык разметки» ((с) Wiki Rus и Wiki Eng):
Originally YAML was said to mean Yet Another Markup Language,[12] referencing its purpose as a markup languagewith the yet another construct, but it was then repurposed as YAML Ain’t Markup Language, a recursive acronym, to distinguish its purpose as data-oriented, rather than document markup.
В той Википедии даже слово «дружественный» взято в кавычки, с чем лично я совершенно солидарен.
Вообще — просто ещё один формат сериализации данных, наследник JSON с дополнительными возможностями.
В недавнем опросе в Ukrainian DevOps Community YAML vs JSON — YAML набрал процентов 90% голосов, так что в самом деле на данный момент является наиболее популярным.
Лично для меня JSON был и остаётся наиболее предпочтительным форматом, но YAML приходится использовать.
Собственно, в этом посте — краткий обзор его основных типов данных и сравнение форматирования с JSON.
Содержание
Основные принципы работы с YAML
- всегда используйте UTF-8 во избежание ошибок
- никогда не используйте TAB для отступов
Валидация YAML
Для проверки синтаксиса YAML в Linux можно использовать yamllint
.
Устанавливаем:
[simterm]
$ sudo pacman -S yamllint
[/simterm]
Проверяем:
[simterm]
$ yamllint monitoring.yml monitoring.yml 1:1 warning missing document start "---" (document-start) 20:34 error trailing spaces (trailing-spaces) 22:32 error trailing spaces (trailing-spaces) 23:37 error trailing spaces (trailing-spaces) 33:7 error wrong indentation: expected 8 but found 6 (indentation) 35:9 error wrong indentation: expected 10 but found 8 (indentation) 36:11 error wrong indentation: expected 12 but found 10 (indentation)
[/simterm]
Правда при этом сам файл парсится Ansibl-ом нормально — но ошибки в форматировании есть.
Валидация JSON
И для примера — валидация JSON-документов из консоли Linux, используя модуль json
:
[simterm]
$ python -m json.tool < json-example.json { "key1": "value1", }
[/simterm]
vim
плагин
Имеется плагин vim-yaml
.
Добавляем в .vimrc
:
... " https://vimawesome.com/plugin/vim-yaml-all-too-well Plug 'avakhov/vim-yaml' " add yaml stuffs au! BufNewFile,BufReadPost *.{yaml,yml} set filetype=yaml foldmethod=indent autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab ...
Перечитываем конфиг, устанавливаем плагин:
[simterm]
:source % :PlugInstall
[/simterm]
PyYAML
Для работы с YAML в Python имеется библиотека PyYAML.
Примеры работы с ней — ниже.
Форматирование в YAML
Комментарии в YAML
Одно из немногих преимуществ — возможность добавления комментариев.
Формат комментирования стандартен — использется #.
Добавление комментария допускается в любом месте строки.
Примеры:
--- # I'm comment - name: somestring value1: "# I'm not a comment!" value: anotherstring # another comment
Отступы
Основная головная боль YAML — отступы.
При этом во всём файле количество пробелов (не табуляций — только пробелы) в начале строк должно быть одинаковым.
Т.е. если для разделения элементов в одном месте используются два пробела — то во всём файле должны использоваться только два пробела, и никак иначе.
Более того — принято использовать 2 пробела, хотя допустимо любое, главное — одинаковое везде и во всём.
Например:
--- parent_key: key1: "value1" key2: "value2" key3: "%value3"
Будет являться валидным форматом, а:
--- parent_key1: key1: "value1" key2: "value2" key3: "%value3" parent_key2: key1: "value1" key2: "value2" key3: "%value3"
Уже нет.
Тогда как в Python, который часто любят ругать за жёсткую привязку к пробелам — такое форматирование допустимо (хоть и будет нарушением стандарта):
#!/usr/bin/env python def a(): print("A") def b(): print("B") a() b()
И результат:
[simterm]
$ python spaces.py A B
[/simterm]
Однострочный YAML
Кроме стандартного вида и разделения пробелами — можно использовать запись в одну строку, аналогично JSON, например:
--- parent_key: {key1: "value1", key2: "value2"}
Literal Block Scalar
YAML поддерживает возможность записи многострочных строковых блочных скаляров и имеет три варианта их записи — обычный, с помощью разделителя «|
» и «>
«.
Обычный формат будет выглядеть так:
--- string: This is some text without newlines
Результат в консоли Python:
[simterm]
>>> yaml.load(open('yaml-example.yml')) {'string': 'This is some text without newlines'}
[/simterm]
При использовании символа | (Literal style) — в значении будут сохранены все символы новой строки и замыкающие пробелы:
--- string: | This is some text with newlines
Результат:
[simterm]
>>> yaml.load(open('yaml-example.yml')) {'string': 'This\nis\nsome text\nwith newlines\n'}
[/simterm]
И с помощью > (Folded style):
--- string: > This is some text without newlines
Что вернёт весь текст одной строкой + замыкающий символ новой строки:
[simterm]
>>> yaml.load(open('yaml-example.yml')) {'string': 'This is some text without newlines\n'}
[/simterm]
При этом — вам всё-равно придётся поддерживать равное кол-во пробелов перед каждой строкой в самом YAML-файле.
См. шикарный ответ на StackOverflow тут>>>:
There are 5 6 NINE (or 63*, depending how you count) different ways to write multi-line strings in YAML.
Базовые форматы данных в YAML
В YAML используются три основных формата:
- scalars: простейший типа ключ:значение
- списки или последовательности (list/sequence): упорядоченные по индексам данные
- словари (dictionary/mapping): схожи со скалярами, но могут иметь вложенные данные в т.ч. других типов
Scalars
Самый простой тип — скаляры, представляющие собой пару ключ:значение:
--- key1: "value1" key2: "value2"
Использование кавычек для строковых данных категорически рекомендуется во избежание проблем со специальными символами:
[simterm]
$ cat example.yml --- key1: "value1" key2: "value2" key3: %value3
[/simterm]
Проверяем:
[simterm]
$ yamllint example.yml example.yml 4:7 error syntax error: found character '%' that cannot start any token
[/simterm]
При этом значения типа true/false и integer можно смело указывать без кавычек.
Scalars — YAML vs JSON
Для сравнения — ключ:значение в YAML:
--- key: "value"
JSON:
{ "key": "value" }
Python
Пример работы с YAML-скалярами в Python:
[simterm]
>>> import yaml >>> yaml.load(""" ... key: "value" ... """) {'key': 'value'}
[/simterm]
Или из файла:
[simterm]
>>> import yaml >>> yaml.load(open('yaml-example.yml')) {'key': 'value'}
[/simterm]
Списки в YAML
Списки (последовательности, lists, sequences, collections) представляют собой коллекции упорядоченных данных, доступ к которым возможен по их индексам.
Пример списка:
# SIMPLE LIST - element1 - element2
Вложенные списки
Аналогично примерам выше — списки могут иметь вложенные списки, например:
# SIMPLE LIST - element1 - element2 # nested list - - element1
Именованные списки:
--- itemname: - valuename
При этом списки могут содержать скаляры или словари (про словари позже):
--- itemname: - valuename - scalar: "value" - dict: {item1: "value1", item2: "value2"}
Lists — YAML vs JSON
Список в YAML:
--- - item1 - item2 - item3
Список в JSON:
[ "item1", "item2", "item3" ]
Вложенный список в YAML:
--- - item1 - item2 - item3 - - nested1
Вложенный список в JSON:
[ "item1", "item2", "item3", [ "nested1" ] ]
Python и YAML-списки
Тут всё аналогично:
[simterm]
>>> yaml.load(open('yaml-example.yml')) ['item1', 'item2', 'item3', ['nested1']] >>> for i in yaml.load(open('yaml-example.yml')): ... print(i) ... item1 item2 item3 ['nested1']
[/simterm]
Словари
Словари, они же dictionaries, они же mappings, схожи со калярами и содержат пары ключ:значение и, в отличии от скаляров, которые являются элементарным типом — могут содержать вложенные элементы:
--- key1: "value1" key2: - value2 - value3
Или вложенные словари:
--- key1: "value1" key2: - value2 - value3 key3: key4: "value4" key5: "value5" key6: key7: "value7"
Dictionary — JSON vs YAML
Словарь в YAML:
--- key1: "value1" key2: - value2 - value3
И он же в JSON:
{ "key1": "value1", "key2": [ "value2", "value3" ] }
Python
[simterm]
>>> yaml.load(open('yaml-example.yml')) {'key1': 'value1', 'key2': ['value2', 'value3']} >>> type(yaml.load(open('yaml-example.yml'))) <class 'dict'>
[/simterm]
И, конечно, доступны все стандартные операции со словарями:
[simterm]
>>> dict = yaml.load(open('yaml-example.yml')) >>> type(dict) <class 'dict'> >>> dict.update({'key3':'value3'}) >>> print(dict) {'key1': 'value1', 'key2': ['value2', 'value3'], 'key3': 'value3'}
[/simterm]
В целом — на этом всё, хотя у YAML много других возможностей.
Смотрите: