Введение

CSS фреймворк. Человекочитаемый формат сериализации данных.

YAML (/'//j//æ//m//ə//l/; см.) — это человекочитаемый язык сериализации данных. Он широко используется для файлов конфигурации и в приложениях, где данные хранятся или передаются. YAML ориентирован на многие из тех же коммуникационных задач, что и Extensible Markup Language (XML), но имеет минималистичный синтаксис, намеренно отличающийся от Standard Generalized Markup Language (SGML), и не требует кавычек вокруг большинства строковых значений (поддерживает также стиль JSON и их смешанное использование в одном файле). Допускаются пользовательские типы данных, но YAML изначально кодирует скаляры (такие как строки, целые числа и числа с плавающей точкой), списки и ассоциативные массивы (также известные как карты, словари или хеши). Эти типы данных основаны на языке программирования Perl, хотя все широко используемые языки программирования высокого уровня имеют очень похожие концепции. Синтаксис с двоеточием для обозначения пар ключ-значение вдохновлен заголовками электронной почты, определенными в , а разделитель документов заимствован из MIME. Экранирующие последовательности используются из C, а переносы строк для многострочных строк вдохновлены HTML. Списки и хеши могут содержать вложенные списки и хеши, образуя древовидную структуру; произвольные графы могут быть представлены с использованием YAML-алиасов (аналогично XML в SOAP). Некоторые редакторы исходного кода, такие как Vim, Emacs и различные интегрированные среды разработки, имеют функции, облегчающие редактирование YAML, например, сворачивание вложенных структур или автоматическое выделение синтаксических ошибок. Официально рекомендованное расширение имени файла для файлов YAML — с 2006 года. В 2024 году был окончательно утвержден MIME-тип . Разработан вместе с Инги дёт Нет и Ореном Бен Кики, поскольку был выпущен в эпоху расцвета языков разметки для представления и обмена данными (HTML, XML, SGML и т. д.). Первоначальное название было задумано как ироничная отсылка к технологическому ландшафту, подчеркивающая его назначение как еще одного языка разметки, но затем было переосмыслено как YAML Ain't Markup Language — рекурсивный акроним, чтобы подчеркнуть его ориентацию на данные, а не на разметку документов.

Версии

Версия Дата выхода YAML 1.0 YAML 1.1 YAML 1.2.0 YAML 1.2.1 YAML 1.2.2

Синтаксис

Лист и полная спецификация доступны на официальном сайте. Ниже приводится краткое изложение основных элементов. YAML принимает весь набор символов Unicode, за исключением некоторых управляющих символов, и может быть закодирован в UTF-8, UTF-16 или UTF-32. (Хотя UTF-32 не является обязательным, он требуется для обеспечения совместимости с JSON для парсера.) Отступы пробелами используются для обозначения структуры; однако символы табуляции не допускаются в качестве части этих отступов. Комментарии начинаются со знака решётки (#), могут начинаться в любом месте строки и продолжаться до её конца. Комментарии должны быть отделены от других токенов пробельными символами. Если символы # встречаются внутри строки, они рассматриваются как литеральные знаки решётки. Элементы списка обозначаются дефисом (-) в начале строки, по одному элементу на строку. Список также можно задать, заключив текст в квадратные скобки [], при этом каждый элемент разделяется запятой. Элемент ассоциативного массива представляется в виде "ключ: значение" с одним элементом на строку. YAML требует, чтобы после двоеточия следовал пробел, чтобы строки в стиле URL могли быть представлены без кавычек. Знак вопроса (?) может быть использован перед ключом в форме "?ключ: значение", чтобы ключ мог содержать начальные дефисы, квадратные скобки и т. д. без кавычек. Ассоциативный массив также можно задать текстом, заключённым в фигурные скобки {}, с ключами, отделёнными от значений двоеточием, а элементы – запятыми (пробелы не требуются для сохранения совместимости с JSON). Строки (один из типов скалярных значений в YAML) обычно не заключаются в кавычки, но могут быть заключены в двойные кавычки " или одинарные кавычки '. Внутри двойных кавычек специальные символы могут быть представлены последовательностями экранирования в стиле C, начинающимися с обратной косой черты \. Согласно документации, поддерживается только восьмеричное экранирование. Внутри одинарных кавычек поддерживается только одна последовательность экранирования – удвоенная одинарная кавычка ', обозначающая саму одинарную кавычку, например ''. Блочные скалярные значения ограничиваются отступами с необязательными модификаторами для сохранения (|) или переноса (|) новых строк. Несколько документов в одном потоке разделяются тремя дефисами ---. Три точки ... необязательно завершают документ в потоке. Повторяющиеся узлы первоначально обозначаются амперсандом &, а затем ссылаются на них с помощью звездочки *. Узлы могут быть помечены типом или тегом с помощью двойного восклицательного знака !!, за которым следует строка, которая может быть расширена до URI. Документам YAML в потоке могут предшествовать "директивы", состоящие из знака процента %, за которым следует имя и параметры, разделенные пробелом. В YAML 1.1 определены две директивы: директива %YAML используется для идентификации версии YAML в данном документе. Директива %TAG используется в качестве сокращения для префиксов URI. Эти сокращения затем могут быть использованы в тегах типов узлов.

Современные компоненты

Две особенности, которые отличают YAML от других языков сериализации данных, — это структуры и типизация данных. Структуры YAML позволяют хранить несколько документов в одном файле, использовать ссылки для повторяющихся узлов и использовать произвольные узлы в качестве ключей. При чтении YAML-парсер раскрывает эти ссылки, преобразуя их в полностью сформированные структуры данных, что позволяет программе, использующей парсер, не учитывать реляционную модель кодирования, в отличие от XML-процессоров, которые не раскрывают ссылки. Такое раскрытие может повысить читаемость и снизить вероятность ошибок при вводе данных в конфигурационных файлах или протоколах обработки, где многие параметры остаются неизменными в последовательности записей, а изменяются лишь некоторые из них. Например, данные для полей "адрес доставки" и "адрес плательщика" в счете-фактуре часто совпадают.

Практические соображения

YAML ориентирован на строки, и поэтому часто бывает просто преобразовать неструктурированный вывод существующих программ в формат YAML, сохраняя при этом большую часть внешнего вида исходного документа. Поскольку в YAML отсутствуют закрывающие теги, скобки или кавычки, требующие балансировки, обычно легко генерировать корректный YAML непосредственно из распределенных операторов печати в простых программах. Аналогичным образом, разделители на основе пробелов облегчают быструю и простую фильтрацию файлов YAML с помощью строкоориентированных команд в grep, AWK, Perl, Ruby и Python. В частности, в отличие от языков разметки, последовательные строки YAML часто сами по себе являются корректными документами YAML. Это позволяет легко создавать парсеры, которым не требуется обрабатывать документ целиком (например, балансировать открывающие и закрывающие теги и обрабатывать заключенные в кавычки и экранированные символы), прежде чем они начнут извлекать конкретные записи. Это свойство особенно полезно при итерации в одном, без сохранения состояния, проходе по записям в файле, чья полная структура данных слишком велика для хранения в памяти, или для которого восстановление всей структуры для извлечения одного элемента было бы непомерно дорогостоящим. Вопреки интуиции, хотя отступы могут казаться усложняющими глубоко вложенные иерархии, YAML обрабатывает отступы, равные даже одному пробелу, что может обеспечить лучшее сжатие, чем языки разметки. Кроме того, чрезмерно глубоких отступов можно полностью избежать либо: 1) переходом к "встроенному стилю" (то есть формату, похожему на JSON) без отступов; либо 2) использованием реляционных якорей для развертывания иерархии в плоскую форму, которую парсер YAML будет прозрачно восстанавливать в полную структуру данных.

Безопасность

YAML - это чисто язык представления данных и, следовательно, не содержит исполняемых команд. Хотя валидация и безопасный разбор данных принципиально возможны в любом языке данных, реализация часто сопряжена с серьезными ошибками, поэтому отсутствие связанного языка команд в YAML может являться относительным преимуществом с точки зрения безопасности. Однако YAML допускает использование тегов, специфичных для языка, что позволяет парсеру, поддерживающему эти теги, создавать произвольные локальные объекты. Любой YAML-парсер, допускающий сложное создание экземпляров объектов, открывает потенциальную возможность для инъекционной атаки. Perl-парсеры, позволяющие загружать объекты произвольных классов, создают так называемые "благословленные" значения. Использование этих значений может привести к неожиданному поведению, например, если класс использует перегруженные операторы. Это может привести к выполнению произвольного кода Perl. Аналогичная ситуация наблюдается и для парсеров Python или Ruby. Согласно документации PyYAML:

Обратите внимание, что возможность создания произвольного объекта Python может быть опасной, если вы получаете YAML-документ из ненадежного источника, например, из Интернета. Функция ограничивает эту возможность простыми объектами Python, такими как целые числа или списки. [ ]

PyYAML позволяет создавать объекты Python любого типа. Даже экземпляры классов Python могут быть созданы с использованием тега.

Обработка и представление данных

Спецификация YAML определяет экземпляр документа как "презентацию" или "поток символов". Основными логическими структурами в документе YAML являются скаляры, последовательности и отображения. Спецификация YAML также устанавливает некоторые базовые ограничения, применимые к этим основным логическим структурам. Например, согласно спецификации, порядок ключей в отображениях не имеет значения. В любом случае, когда порядок узлов существенен, необходимо использовать последовательность. Более того, при определении соответствия процессоров YAML спецификация определяет две основные операции: дамп и загрузка. Все процессоры, соответствующие требованиям YAML, должны поддерживать как минимум одну из этих операций, и могут поддерживать обе. Наконец, спецификация YAML определяет информационную модель или "граф представления", который должен создаваться в процессе обработки как для операции дампа, так и для операции загрузки, хотя это представление необязательно должно быть доступно пользователю через API.

Сравнение с JSON

Синтаксис JSON является основой версии YAML 1.2, которая была опубликована с четкой целью привести YAML "в соответствие с JSON как с официальным подмножеством". Различия были редко заметны, и большинство JSON-документов могут быть разобраны некоторыми YAML-парсерами, такими как Syck. Это происходит потому, что семантическая структура JSON эквивалентна необязательному "встроенному стилю" записи YAML. Хотя разветвленные иерархии могут быть записаны во встроенном стиле, как в JSON, это не является рекомендуемым стилем YAML, за исключением случаев, когда это способствует ясности. YAML обладает множеством дополнительных функций, которых нет в JSON, включая комментарии, расширяемые типы данных, реляционные якоря, строки без кавычек и типы отображений, сохраняющие порядок ключей. Благодаря своей лаконичности, сериализация и десериализация JSON значительно быстрее, чем YAML.

Сравнение с TOML

TOML был разработан как усовершенствование формата файлов ini. Минимальное использование индикаторов в YAML выгодно отличается от строгого требования TOML к использованию кавычек и квадратных скобок. Использование значимых отступов в YAML противопоставляется точечной нотации ключей и имен таблиц в TOML, которая позволяет передать ту же семантическую структуру. Вопрос о том, какая из этих практик приводит к более читаемым файлам конфигурации, является предметом споров среди программистов.

Сравнение с XML

В YAML отсутствует понятие атрибутов тегов, как в XML. Вместо этого YAML использует расширяемые объявления типов (включая типы классов для объектов). Сам по себе YAML не имеет встроенных описателей схем документов, определенных языком, как в XML, которые позволяли бы документу самопроверяться. Однако существует несколько внешних языков описания схем для YAML (например, Doctrine, Kwalify и Rx), выполняющих эту функцию. Более того, семантика, обеспечиваемая объявлениями типов, определенными в самом документе YAML, часто снижает потребность в валидаторе в простых и распространенных случаях. Кроме того, YAXML, представляющий структуры данных YAML в формате XML, позволяет применять к YAML импортеры схем XML и механизмы вывода, такие как XSLT. Более полное сравнение YAML с другими форматами сериализации представлено в разделе "Сравнение форматов сериализации данных".

Программное обеспечение (эмиттеры и анализаторы)

Для фиксированных структур данных файлы YAML могут быть просто сгенерированы с помощью команд печати, которые записывают как данные, так и специфическое оформление YAML. Однако для вывода изменяющихся или сложных иерархических данных предпочтительнее использовать выделенный YAML-излучатель. Аналогично, простые файлы YAML (например, пары ключ-значение) легко разбираются с помощью регулярных выражений. Для более сложных или изменяющихся структур данных рекомендуется использовать формальный YAML-парсер. YAML-излучатели и парсеры существуют для многих популярных языков программирования. Большинство из них написаны на родном языке. Некоторые являются языковыми привязками к C-библиотеке libyaml; они могут работать быстрее. Ранее существовала другая C-библиотека под названием Syck, написанная и заброшенная why the lucky stiff: она больше не поддерживается, нет авторитетного исходного пакета, а веб-сайт был взломан. Следовательно, единственной рекомендуемой C-библиотекой является libyaml. Она была первоначально разработана Кириллом Симоновым. В 2018 году разработка была возобновлена новыми сопровождающими Ианом Кордаско и Инги дёт Нет. Программисты на C++ могут выбирать между C-библиотекой libyaml и C++-библиотекой libyaml-cpp. Обе имеют полностью независимые кодовые базы и совершенно разные API. Библиотека libyaml-cpp по-прежнему имеет мажорный номер версии 0, что указывает на то, что API может измениться в любой момент, как это и произошло после версии 0.3. Существует реализация, ориентированная на грамматику, написанная на C#, с целью расширения для вложенных элементов. Некоторые реализации YAML, такие как Perl's YAML.pm, загружают весь файл (поток) и разбирают его целиком. Другие реализации, такие как PyYaml, ленивы и переходят к следующему документу только по запросу. Для очень больших файлов, в которых планируется обрабатывать документы независимо, создание экземпляра всего файла перед обработкой может быть нецелесообразным. Таким образом, в YAML.pm иногда необходимо разбивать файл на документы и разбирать их по отдельности. YAML упрощает это, поскольку для этого достаточно разделить файл по конечному маркеру документа, который определяется как три точки в начале строки, за которыми следует пробел (и, возможно, комментарий). Этот маркер запрещен в содержимом.