Форматтер YAML
Форматтер YAML приводит документ к единому виду: отступы 2 или 4 пробела, кавычки, списки. Показывает типичные ошибки YAML с номером строки.
Зачем приводить YAML к единому виду
YAML форматтер нужен там, где YAML уже написан, но выглядит по-разному: один человек ставит два пробела, другой четыре, третий пользуется табуляцией, а ключи кое-где в кавычках, кое-где без. Формально всё это допустимо, и любой парсер такой файл прочитает. Практически же такой файл невозможно ревьюить: при диффе глаза цепляются не за смысл, а за пробелы. Отсюда две практические задачи. Первая — привести существующий документ к одному виду, чтобы изменения в нём были видны как изменения данных, а не как шум. Вторая — найти то, что мешает парсеру: табуляцию в отступе, двоеточие без пробела, незакрытую кавычку, повторяющийся ключ. Ниже разобран разбор файла с ошибками, а таблица показывает, что именно делает форматтер с каждым видом дефекта.
Что умеет форматтер YAML
- Два режима: нормализация с отступами и сворачивание всего документа в одну строку
- Отступы 2 или 4 пробела на выбор — как принято в вашем проекте
- Списки приводятся к единому виду: каждый пункт с дефисом, вложенные объекты выровнены
- Лишние кавычки снимаются, но только там, где тип значения не изменится
- Ключи можно отсортировать по алфавиту, чтобы порядок не зависел от того, кто редактировал файл
- Список проблем с номером строки: табы, разный шаг отступа, двоеточие без пробела, незакрытая кавычка, дубли ключей
Как пользоваться форматтером
- Вставьте YAML в поле ввода — можно целиком из файла, можно фрагментом
- Выберите режим: нормализация для чтения или минимизация для вставки в код
- Задайте ширину отступа и при необходимости включите сортировку ключей
- Нажмите «Нормализовать» и заберите результат кнопкой копирования
- Если в списке ошибок есть записи, исправьте их в исходном тексте и прогоните ещё раз
Как устроен разбор
Разбор написан вручную, без внешних библиотек, и состоит из трёх проходов. Сначала каждая строка очищается от комментария: знак # внутри кавычек комментарием не считается. Затем по отступам строится дерево: отступ задаёт уровень вложенности, дефис в начале строки — пункт списка, двоеточие с пробелом — границу между ключом и значением. Третий проход обходит дерево и собирает текст заново: с выбранной шириной отступа, единым видом списков и кавычками по правилам. Отдельно проверяются табуляция в отступе, несовпадение шага отступа между соседними блоками, баланс кавычек в строке и повторяющиеся ключи внутри одного отображения. Одна оговорка: полноценный YAML 1.1 с якорями, псевдонимами, тегами и несколькими документами не поддерживается, ровно как в конвертере YAML в JSON.
Что форматтер делает с типичными ошибками
| Было в файле | Что сделано | Стало |
|---|---|---|
| name:Alice | добавлен пробел после двоеточия | name: Alice |
| a: b: 1 | табуляция заменена отступом в два пробела | a: b: 1 |
| a: b: 1 c: d: 2 | отступ приведён к шагу, принятому в документе | a: b: 1 c: d: 2 |
| title: "Пример" | лишние кавычки сняты | title: Пример |
| port: "8080" | кавычки оставлены, иначе число стало бы строкой | port: "8080" |
| flag: "true" | кавычки оставлены, иначе булево значение стало бы строкой | flag: "true" |
| items: [1, 2, 3] | потоковый список развёрнут в обычный | items: - 1 - 2 - 3 |
| a: 1 a: 2 | показан повторяющийся ключ, строки указаны | a: 1 a: 2 |
| text: "строка | показана незакрытая кавычка | text: "строка |
| log: /var/log/app.log | значение оставлено как есть | log: /var/log/app.log |
| script: | line 1 line 2 | блочный скаляр сохранён |
| b: 2 a: 1 | ключи отсортированы по алфавиту | a: 1 b: 2 |
Часть строк показана с переносом строки внутри ячейки: так видно, где именно менялся отступ.
Где YAML приходится приводить к единому виду
Первый и самый заметный случай — конфигурация в репозитории, которую правили несколько человек. Каждый привык к своему отступу, и через полгода файл состоит из четырёх разных стилей в одном экране. При таком раскладе любой diff выглядит как переписывание всего файла, и ревью перестаёт работать: никто не способен разглядеть в шуме одну изменённую строку. Нормализация решает эту проблему механически: отступы становятся одинаковыми, списки одинаковыми, кавычки одинаковыми, и дальше в диффе остаются только данные.
Второй случай — файл, который пишут автоматически. Генератор шаблонов, скрипт выгрузки, настройка CI: каждая такая штука печатает YAML по-своему, и на выходе получается документ, который никто не читал глазами. Перед тем как такой файл уедет в продакшен, его полезно прогнать через форматтер: он станет предсказуемым, и любая следующая правка в нём будет видна. Третий случай — ручная правка большого конфига в редакторе без подсветки YAML: там особенно часто появляются табы и забытые пробелы после двоеточия.
- Конфигурация в git, которую правили несколько разработчиков
- Файл, который генерируется скриптом и уходит в CI
- Правка большого docker-compose в редакторе без подсветки
- Объединение двух версий конфига, написанных в разных стилях
- Подготовка файла к выкладке, где важна предсказуемость
- Проверка чужого файла перед добавлением в свой проект
Что ломается в YAML чаще всего
Первое место в списке — табуляция. Её набирают не специально: редактор подставил её вместо пробелов, человек не заметил, потому что на экране отступ выглядит ровно. Вторая ошибка — лишний пробел или его отсутствие после двоеточия. С виду разница невелика, но YAML требует пробел, и без него ключ не отделяется от значения. Третья — незакрытая кавычка: обычно она возникает при копировании строки из одного файла в другой, когда кавычка «проезжает» вместе с текстом.
Четвёртая ошибка — дубликат ключа. Её нетрудно получить, скопировав блок и забыв удалить исходный. Пятая — разный шаг отступа в соседних блоках: выглядит безобидно, пока файл не начинают читать другие инструменты. И шестая, самая коварная, — значения, которые меняют тип при снятии кавычек. «true» в кавычках это строка, без кавычек это булево значение, и код, который сравнивает поле с true, внезапно перестаёт работать. Хороший форматтер не должен молча менять смысл, поэтому такие значения он не трогает.
- Табуляция вместо пробелов в отступе
- Двоеточие без пробела после: name:Alice
- Незакрытая кавычка в строке со значением
- Повторяющийся ключ внутри одного блока
- Разный шаг отступа у соседних блоков
- Кавычки, снятие которых меняет тип значения
Разбор файла с ошибками по шагам
Возьмём файл, в котором смешались четыре типовые проблемы. Первая строка содержит табуляцию в отступе, вторая — двоеточие без пробела, третья — повторяющийся ключ, четвёртая — незакрытую кавычку. Форматтер сначала очищает каждую строку от комментария, аккуратно не трогая знак # внутри кавычек, потом строит дерево по отступам и уже по дереву собирает новый текст.
Порядок важен: сначала убираются комментарии, потому что в комментарии может встретиться двоеточие или фигурная скобка, которые иначе были бы приняты за структуру. Затем приводятся к одному виду отступы и списки, и только в конце снимаются лишние кавычки — когда уже известно, какое значение получилось и не поменяет ли оно тип. Проверка при этом идёт параллельно: каждая найденная проблема попадает в список с номером строки, чтобы по ней можно было сразу перейти к нужному месту в исходнике.
Что происходит на каждом шаге разбора
| Шаг | Действие | Результат |
|---|---|---|
| 1 | Очистка строк | Комментарии убраны, # внутри кавычек сохранён |
| 2 | Определение отступа | Пробелы посчитаны, табуляция отмечена |
| 3 | Разбор пар ключ и значение | Двоеточие с пробелом делит строку |
| 4 | Сборка дерева | Дефис в начале строки означает пункт списка |
| 5 | Проверки | Табы, шаг отступа, кавычки, дубликаты |
| 6 | Сборка ответа | Отступы и списки приведены к единому виду |
| 7 | Кавычки | Снимаются только там, где тип не меняется |
| 8 | Проверка результата | Текст разбирается заново |
Разбор линейный: он делает несколько проходов по строкам, поэтому размер файла на скорость почти не влияет.
Форматтер, конвертеры и проверка JSON
Форматтер YAML стоит рядом с конвертерами в других форматы, и между ними есть разница, о которой стоит сказать прямо. Конвертер в JSON меняет формат: то, что было YAML, становится данными, которые можно передать в код. Форматтер формат сохраняет и трогает только запись. На практике их часто используют вместе: сначала нормализуют, чтобы diff был читаемым, потом конвертируют, чтобы отдать данные приложению. Обратный путь тоже работает: из JSON получают YAML, и если исходный JSON был сгенерирован машиной, его приводят к тому же единому виду.
Отдельно стоит сказать про проверку. Форматтер отвечает на вопрос «читается ли этот файл», но не на вопрос «правильные ли в нём данные». Для второго есть валидатор JSON Schema, а для сравнения двух версий одного файла — сравнение JSON и разница текстов. Именно эти инструменты помогают ответить, что именно изменилось в данных, когда формат уже приведён к единому виду и шума больше нет.
- Форматтер отвечает на вопрос «читается ли файл»
- Конвертеры отвечают на вопрос «в каком формате отдать данные»
- Порядок работы: сначала формат, потом смысл
- Сравнение версий имеет смысл только после нормализации
- Проверка по схеме — отдельный слой и отдельный инструмент
- Форматирование JSON решает ту же задачу для другого формата
Частые вопросы
Чем форматтер YAML отличается от конвертера в JSON
Почему YAML нельзя парсить табуляцией
Когда нужно ставить отступ в 4 пробела, а когда в 2
Что будет, если в файле два одинаковых ключа
Что значит ошибка про значение с двоеточием
Умеет ли форматтер проверять YAML по схеме
Почему снимаются не все кавычки
Что происходит с YAML 1.1, якорями и псевдонимами
Похожие инструменты
Конвертер XML в JSON
Преобразование XML в JSON: массивы, атрибуты, текст и CDATA в понятной схеме
Починка JSON
Восстановление битого JSON: комментарии, кавычки, висячие запятые, переносы строк
Форматирование и валидация JSON
Форматирование, украшение, валидация и минификация JSON с древовидным просмотром
Форматирование XML
Форматирование, украшение, минификация и валидация XML документов
Конвертер CSV в JSON
Конвертация данных CSV в формат массива JSON с настраиваемыми разделителями
JSON в TypeScript
Сгенерируйте TypeScript-интерфейсы из любого JSON — с вложенными объектами и массивами.
Конвертер JSON в CSV
Конвертация массива JSON в формат CSV с автоопределением столбцов
Конвертер JSON в YAML
Конвертация данных JSON в формат YAML с правильными отступами