YAML против JSON против TOML — Какой формат конфигурации вам действительно следует использовать?
YAML, JSON и TOML хранят настройки. Они не являются взаимозаменяемыми. YAML безусловно превращает ваш код страны в логическое значение. JSON не позволяет оставить комментарий. TOML — это тот, который никто из вашей команды ранее не использовал. Вот как выбрать правильный вариант.
В 2015 году плейбук Ansible сломался из-за этой строки:
country: NO
Конфигурация загружалась без ошибок. Нет жалоб на парсер. Но country не была установлена в строку "NO". Она была установлена в false. Поскольку в YAML 1.1, NO является логическим значением. Так же и yes, on, off, yи n. Это проблема Норвегии, и она уже годами тихо коррумпирует конфигурации.
Это не отчёт о баге YAML. Это рамка для решения, которое вы собираетесь принять: YAML, JSON или TOML для вашего следующего файла конфигурации? У каждого из них есть реальные компромиссы, и ответ «просто используйте то, что использует экосистема» не всегда применим.
Та же конфигурация, три способа
Перед разрушением, вот та же конфигурация приложения, написанная в трёх форматах:
ЯМЛ
# App configuration
app:
name: my-api
port: 8080
debug: false
database:
host: localhost
port: 5432
name: mydb
pool_size: 10
logging:
level: info
format: json
outputs:
- stdout
- /var/log/app.log
JSON
{
"app": {
"name": "my-api",
"port": 8080,
"debug": false
},
"database": {
"host": "localhost",
"port": 5432,
"name": "mydb",
"pool_size": 10
},
"logging": {
"level": "info",
"format": "json",
"outputs": [
"stdout",
"/var/log/app.log"
]
}
}
ТОМЛ
# App configuration
[app]
name = "my-api"
port = 8080
debug = false
[database]
host = "localhost"
port = 5432
name = "mydb"
pool_size = 10
[logging]
level = "info"
format = "json"
outputs = ["stdout", "/var/log/app.log"]
YAML — самый компактный, но самый синтаксически насыщенный. JSON — самый подробный, но самый прозрачный. TOML находится в середине: читаемый без имплицированных типовых преобразований YAML.
YAML: Сильный, гибкий и полный ловушек
YAML является стандартным выбором для CI/CD-процессов (GitHub Actions, GitLab CI, CircleCI), манифестов Kubernetes, плейбуков Ansible и большинства инструментов разработчиков. Вы не выбираете YAML — он выбирает вас.
Ловушки, документированные:
1. Проблема логических значений (проблема Норвегии)
YAML 1.1 — спецификация, которую большинство парсеров фактически реализуют — рассматривает большое количество строк как логические значения:
# YAML 1.1 boolean values (all parsed as true or false)
enabled: yes # true
disabled: no # false
active: on # true
paused: off # false
valid: true # true
invalid: false # false
# The Norway Problem in practice:
country_codes:
NO: Norway # Key "NO" is fine, but value "NO" becomes false
SE: Sweden
YES: Yemen # "YES" also becomes true
# The fix: quote your strings
country_codes:
NO: "Norway"
SE: "Sweden"
YAML 1.2 (выпущена в 2009 году) это исправило — только true и false являются логическими значениями. Проблема в том, что PyYAML не полностью перешёл к поведению 1.2 до версии 6.0 в 2021 году, а Go-парсер gopkg.in/yaml.v2 по-прежнему использует семантику 1.1 на 2024 год. Если вы используете Ruby Psych < 4.0 или любую версию PyYAML до 6.0, вы работаете с версией 1.1.
2. Табу убьёт вашу конфигурацию
YAML запрещает использование символов табуляции для отступов. Только пробелы являются допустимыми. Ваш редактор может отображать табуляцию и пробелы одинаково, файл может выглядеть корректно, но YAML всё равно выбросит:
yaml.scanner.ScannerError: while scanning a block mapping
found character '\t' that cannot start any token
Это ошибка, которая заставляет молодых разработчиков сомневаться в своём выборе карьеры. Настройте ваш редактор так, чтобы табуляции расширялись в пробелы в файлах YAML. Каждый редактор поддерживает это; не каждый редактор включает это по умолчанию.
3. Многострочные строки не очевидны
# | (literal block): preserves newlines exactly
description: |
Line one.
Line two.
Line three.
# Result: "Line one.\nLine two.\nLine three.\n"
# > (folded block): folds newlines into spaces
short_desc: >
This will all become
one long line.
# Result: "This will all become one long line.\n"
# Trailing newlines: | adds one, |+ adds all, |- strips them all
desc_stripped: |-
No trailing newline.
Никто не запоминает это без поиска в справочнике. Мнемоника, которую я использую: | выглядит как перенос строки, > выглядит как что-то, сжатое вместе. Это всё ещё путано уже через три года.
Когда YAML выигрывает
- Вы пишете манифесты Kubernetes, рабочие потоки GitHub Actions или плейбуки Ansible — у вас нет выбора.
- Ваша конфигурация содержит много комментариев, объясняющих неочевидные значения. YAML поддерживает встроенные комментарии; JSON и TOML также поддерживают их, но YAML кажется наиболее естественным для конфигураций с большим объёмом аннотаций.
- Ваша структура данных имеет глубоко вложенные структуры, которые выглядели бы ужасно при использовании плоских таблиц TOML.
- Команда уже владеет этим и имеет линтер (yamllint) в процессе разработки.
JSON: Сухой, надёжный рабочий инструмент
JSON был разработан как формат обмена данными, а не как формат конфигурации. Дуглас Крочфорд намеренно исключил комментарии — его аргумент был в том, что комментарии будут использоваться для директив, на которые парсеры могут не согласоваться. Именно поэтому package.json не имеет комментариев и tsconfig.json является технически JSON с комментариями (JSONC), что является отдельным форматом, не поддерживаемым большинством JSON-парсеров.
Реальные проблемы JSON для конфигурационных файлов:
- Отсутствие комментариев. Вы не можете объяснить, почему
"maxRetries": 3и не 5. Вы не можете оставить TODO. Вы не можете пометить поле как устаревшее. Это действительно болезненно для конфигурационных файлов, которые превышают сроки их авторов. - Отсутствие завершающих запятых. Добавление элемента в массив означает изменение предыдущей строки для добавления запятой. Каждое изменение JSON становится изменением в две строки. Каждый конфликт слияния становится немного хуже, чем нужно.
- Несмотря на то, что для вложенных данных JSON является слишком подробным. Шесть строк скобок и квадратных скобок для того, что YAML делает за три строки отступов.
- Все числа имеют одинаковый тип. JSON не различает целые и вещественные числа.
1и1.0оба являются просто числами, и то, как ваша программа их десериализует, зависит от парсера.
Но предсказуемость JSON также является его главным преимуществом. У каждой языка есть JSON-парсер. Спецификация является однозначной. Нет имплицированных типовых преобразований. Строка всегда остаётся строкой — "yes" никогда не превращается в true. Если вам нужно программно проверить конфигурацию JSON, IO Tools’ JSON Formatter может обнаружить синтаксические ошибки до того, как они попадут в производство — полезно, когда кто-то ручным образом редактирует конфигурацию и забывает добавить завершающую запятую.
Когда JSON выигрывает
- Конфигурации, которые потребляются несколькими сервисами или языками. JSON универсален; поддержка TOML в некоторых экосистемах нестабильна.
- Вы нуждаетесь в строгих гарантиях типов. Валидация схем JSON зрелая, хорошо поддерживается и широко используется (VS Code использует её для автозаполнения настроек).
- Конфигурация генерируется машиной. Никто не пишет JSON вручную, если это возможно — но машины генерируют его без проблем.
- Вы работаете в Node.js или в фронтенд-JavaScript, где JSON является инструментом по умолчанию.
TOML: Конфигурация с уклоном, сделанная правильно
TOML (Tom’s Obvious, Minimal Language) была создана Томом Пренстон-Вернером, со-основателем GitHub, специально для конфигурационных файлов. Она достигла версии 1.0 в январе 2021 года. Это стандартный формат для Rust’а Cargo.toml, Python’а pyproject.tomlи статических сайтов Hugo.
Философия дизайна TOML: типы должны быть явными, структура должна быть плоской, где возможно, и должно быть ровно одно очевидное решение для записи любого значения конфигурации.
# Types are unambiguous in TOML
name = "my-app" # string: always quoted
port = 8080 # integer
threshold = 3.14 # float
enabled = true # boolean: only true/false, no yes/no
created = 2024-01-15 # date: native type
tags = ["api", "prod"] # array
# "yes" is just a string. Always.
country = "NO" # string "NO", no boolean nonsense
Недостатки:
- Синтаксис массивов таблиц действительно неудобен.
[[products]]и[products.details]выглядят похоже, но ведут себя совершенно по-разному. Спецификация имеет смысл; визуальное различие не подчёркивает. - Глубокая вложенность становится громоздкой. То, что YAML делает за 5 отступов, TOML делает за 3 отдельных заголовка секции. Для конфигураций более чем на 3 уровня глубины, TOML начинает казаться неподходящим инструментом.
- Доступность парсеров. Парсеры TOML существуют для всех основных языков, но они варьируются по степени соответствия спецификации. Тест-сборник TOML compliance test suite регулярно выявляет крайние случаи. Парсеры JSON проходят гораздо больше тестов по использованию.
- Опыт команды. Если вы используете TOML вне экосистемы Rust или Python, ожидайте, что хотя бы один член команды откроет PR с вопросом «что это за формат?»
Когда TOML выигрывает
- Проекты на Rust —
Cargo.tomlявляется стандартом и инструменты отличные. - Проекты на Python, использующие
pyproject.toml(PEP 518) — это теперь рекомендуемое место для конфигурации инструментов, таких как Black, Ruff, mypy и pytest. - Простые, плоские конфигурации, где чувствительность к отступам YAML будет являться недостатком.
- Вы хотите поддержку дат и времени без сериализации в строки.
Быстрый руководство по выбору
- Kubernetes / CI/CD / Ansible? YAML. Нет выбора.
- Конфигурация API, потребляемая несколькими сервисами в разных языках? JSON.
- Проект на Rust? TOML (по умолчанию Cargo.toml).
- Конфигурация проекта на Python (инструменты, форматы, сборка)? TOML (pyproject.toml — стандарт сейчас).
- Конфигурация статического сайта (Hugo, Zola)? TOML, хотя эти обычно поддерживают все три.
- Конфигурация проекта на Node.js? JSON (экосистема package.json), или YAML, если вам нужны комментарии.
- Люди будут часто редактировать это и оставлять заметки? YAML или TOML (оба поддерживают комментарии). Не JSON.
- Вы хотите строгую типовую безопасность и валидацию схемы? JSON + JSON Schema.
Честный ответ для большинства новых проектов: используйте то, что ожидает основной язык экосистемы. Rust ожидает TOML. Инструменты на Python ожидает TOML или YAML. Node.js ожидает JSON. Если вы пишете что-то универсальное, TOML для конфигурации, редактируемой людьми, и JSON для конфигурации, генерируемой машиной и потребляемой машиной — это разумный стандартный выбор.
Установите наши расширения
Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска
恵 Табло результатов прибыло!
Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!
Подписаться на новости
все Новые поступления
всеОбновлять: Наш последний инструмент было добавлено 18 Июня, 2026
