JSON, TOML, YAML или CSON: выбор формата конфигурации
Главное: Конфигурационным файлам нужны комментарии, даты и многострочный текст — вот где JSON не справляется. Сравните JSON, TOML, YAML и CSON и посмотрите, что конвертация всегда теряет.

Главное: используйте JSON для машинного обмена и выбирайте TOML или YAML для конфигурации, поддерживаемой людьми, в соответствии с экосистемой (YAML для Kubernetes и CI, TOML для плоских структур или нативных дат); откатывайтесь к JSONC только когда не уверены, что читатель поддерживает диалект.
JSON существует для машин, обменивающихся данными; конфигурационный файл пишут люди для людей. Смешайте одно с другим, и вы получите
config.json, который не может вместить комментарий и который никто не смеет подрезать.
1. Начните с двух разных типов файлов
Обмен данными и конфигурация не разделяют одну цель, хотя один и тот же человек часто пишет и то, и другое на одной машине.
| Аспект | Обмен данными | Конфигурация |
|---|---|---|
| Кто пишет | Программа, сериализующая значение | Человек или человек, редактирующий сгенерированный вывод |
| Кто читает | Чужая программа | Ваша собственная программа |
| Что важно | Нулевая неоднозначность, размер, скорость парсинга | Читаемость, комментарии, поддающиеся ревью различия |
| Частота изменений | Каждый запрос | Изредка, с ревью |
| Цена ошибки | Ответ 500 | Сервис, который не запустится |
JSON почти идеально выигрывает в левом столбце: минимальная грамматика, парсер в каждом языке, и отсутствие комментариев означает отсутствие проблемы «комментарий оторвался от значения». В правом столбце его строгость — чистое трение: без комментариев, без висячих запятых, без дат, а многострочный текст нужно схлопывать в одну строку с \n.
2. Четыре претендента и их синтаксис
- JSON: определён RFC 8259 и ECMA-404, ровно шесть типов значений: объект, массив, строка, число, булево и
null. Это де-факто стандарт обмена и единственный формат, не требующий решения о выборе. - TOML: создан Томом Престон-Вернером, версия v1.0.0 опубликована в январе 2021. Его заявленная цель — минимальный формат конфигурации с очевидной семантикой, который однозначно отображается в хеш-таблицу.
Cargo.tomlиpyproject.tomlиспользуют его по умолчанию. - YAML: текущая спецификация — 1.2.2. Отступы выражают иерархию, и он поддерживает комментарии, якоря и несколько документов. Манифесты Kubernetes, GitHub Actions и Ansible все зависят от него ценой большого объёма спецификации и различий реализаций.
- CSON: CoffeeScript Object Notation, который пишет конфигурацию через литералы объектов CoffeeScript.
config.csonв Atom использовал его. Он поддерживает комментарии, ключи без кавычек и висячие запятые, но его экосистема никогда не покидала мир JavaScript.
2.1 Сравнение возможностей
| Возможность | JSON | TOML | YAML | CSON |
|---|---|---|---|---|
| Комментарии | ✗ | ✓ # |
✓ # |
✓ # |
| Висячие запятые | ✗ | ✓ (массивы, inline-таблицы) | ✓ (flow-коллекции) | ✓ |
| Ключи без кавычек | ✗ | ✓ | ✓ | ✓ |
| Нативные дата-время | ✗ (только строка) | ✓ четыре типа дата-время | ✓ (автопарсинг в 1.1) | ✗ |
| Многострочные строки | ✗ (escape-последовательности \n) |
✓ """ и ''' |
✓ блочные и свёрнутые скаляры | ✓ heredoc |
| Диапазон целых | Не ограничен в спецификации, double на практике | Знаковые 64 бита, должны быть без потерь | Произвольная точность плюс .inf/.nan |
Следует JavaScript |
| Вложенность | Скобки и квадратные скобки | Таблицы, массивы таблиц, точечные ключи | Отступы | Отступы |
| Чувствительность к отступам | ✗ | ✗ | ✓ | ✓ |
null |
✓ | ✗ | ✓ | ✓ |
| Покрытие инструментами | Каждый язык | Основные языки | Каждый язык, различающиеся реализации | Только JavaScript |
Две ячейки заслуживают примечания. В TOML нет null, что является самой частой ошибкой при конвертации из JSON. Поведение «нативной даты» в YAML означает, что парсер 1.1 автоматически превращает 2026-10-31 в объект даты, поэтому тип дрейфует между языками.
3. Комментарии: единственная слабость JSON
Сначала вывод: если файл поддерживает человек и ему нужно объяснить, почему значение такое, не используйте стандартный JSON.
Есть четыре практических пути, по степени инвазивности:
- Перейти на JSONC — это стандартный JSON плюс комментарии и висячие запятые. Его используют
settings.jsonиtsconfig.jsonв VS Code. Цена — читатель должен использовать парсер, понимающий комментарии, напримерjsonc-parser; обычныйJSON.parseпадает. Подробности в JSON5 и JSONC: JSON с комментариями. - Держите sidecar-документ.
config.jsonостаётся машиночитаемым, аconfig.mdобъясняет, что означает каждое поле и почему оно имеет такое значение. Оба живут в одном каталоге и меняются в одном коммите. - Поместите объяснения в схему. Ключевые слова
descriptionи$commentв JSON Schema могут документировать поля, но схемы редко поставляются вместе с конфигурацией во время выполнения, поэтому человек, читающий конфигурацию, может никогда их не увидеть. - Перейдите на TOML или YAML, позволив самому формату обеспечить комментарии, которые понимает каждый парсер.
{
// Fixed at 8080: the frontend build script reads this port for its proxy
"port": 8080,
// Disable watching to avoid exhausting inodes in CI
"watch": false
}
JSONC всё ещё диалект: расширение остаётся .json, но понимают его только некоторые инструменты. Когда данные покидают команду или пересекают границу сервиса, граница между JSONC и стандартным JSON должна быть документирована.
4. Даты и многострочные строки: родная территория TOML
TOML повышает дата-время до типа первого класса с четырьмя вариантами: дата-время со смещением, локальная дата-время, локальная дата и локальное время. Многострочные строки имеют выделенный синтаксис, сохраняющий переводы строк:
title = "json-toolkit"
created = 2026-10-31T09:00:00+08:00
description = """
A JSON toolkit for developers.
Every operation runs locally in the browser.
"""
Ту же информацию в JSON приходится понижать до строки и экранировать переводы строк:
{
"title": "json-toolkit",
"created": "2026-10-31T09:00:00+08:00",
"description": "A JSON toolkit for developers.\nEvery operation runs locally in the browser."
}
В JSON "created" — просто строка, которая случайно выглядит как дата, поэтому информация о типе должна жить в контракте поля: обе стороны должны согласиться, что поле всегда RFC 3339. TOML даёт парсеру настоящий объект даты без словесного соглашения.
YAML тоже может держать многострочный текст, но два блочных стиля означают разное: | сохраняет переводы строк, а > сворачивает их в пробелы. Выберите неверный, и адрес или SQL-выражение схлопнется в одну строку — ошибка, которую очень трудно ловить при ревью.
5. Числа: самое упускаемое различие
Спецификация JSON не накладывает ограничения на числовую точность, но RFC 8259 также предупреждает, что совместимость безопаснее всего, когда числа трактуются как double IEEE 754. В JavaScript целые выше 2^53 - 1 молча теряют точность:
JSON.parse('{"id":9007199254740993}').id
// 9007199254740992: the last digit is gone
TOML требует, чтобы знаковые 64-битные целые обрабатывались без потерь и поднимали ошибку вместо молчаливого усечения; числа с плавающей точкой следуют binary64 и могут также быть inf или nan. YAML 1.1 несёт более старое бремя: 1:30 разбирается как 90 (шестидесятеричная система), а булевы принимают yes, no, on и off. Отсюда классическая «проблема Норвегии», где код страны NO становится false.
Для денег никогда не полагайтесь на плавающую точку ни в одном из этих форматов: используйте целые минорные единицы, строки или десятичный тип базы данных. Форматирование и точность глубже рассмотрены в границах конвертации JSON, YAML и XML.
6. Таблицы и вложенность: жёсткие границы TOML
TOML выражает вложенность через таблицы и массивы таблиц:
[server]
port = 8080
[[routes]]
path = "/parse"
method = "POST"
[[routes]]
path = "/minify"
method = "POST"
У него есть две жёсткие границы, которые нужно знать до конвертации:
- Корень документа TOML — таблица, поэтому документ JSON, верхний уровень которого является массивом (например,
[1, 2, 3]), не имеет легального представления в TOML; его нужно обернуть как{"items": [...]}; - В TOML нет
null, поэтому полеnullв JSON нужно либо удалить, либо заменить пустой строкой или сигнальным значением, перенеся семантику на потребителя.
YAML — противоположность: глубина вложенности неограничена, а якоря плюс ключи слияния могут переиспользовать фрагменты:
defaults: &defaults
retries: 3
timeoutMs: 5000
server:
<<: *defaults
port: 8080
Якоря — возможность только YAML и гарантированная потеря при конвертации: в JSON нет синтаксиса ссылок, поэтому развёрнутый файл растёт, и ничто не записывает, что два раздела когда-то были одной конфигурацией.
7. Выбор по сценарию
| Сценарий | Рекомендация | Причина |
|---|---|---|
| Публичные API, очереди сообщений, кеши | JSON | Максимальная универсальность, нулевая стоимость согласования |
| Конфигурация приложения, плоская и типизированная | TOML | Комментарии, даты, целые без потерь, стабильное поведение парсера |
| Kubernetes, CI, Ansible | YAML | Экосистема зафиксирована; смена формата означает смену инструментов |
VS Code, tsconfig.json |
JSONC | Поддерживается нативно, не нужно вводить новый формат |
| Переиспользование фрагментов конфигурации | YAML | Якоря и ключи слияния — единственный готовый вариант |
| Сгенерированное и только для машин | JSON (минифицированный) | Комментарии не нужны, лучший размер и стоимость парсинга |
| Наследные проекты Atom или CoffeeScript | CSON, но планируйте миграцию | Экосистема маргинальна, а стоимость миграции растёт со временем |
Одно правило большого пальца: пусть экосистема выбирает формат конфигурации, а не личные предпочтения. Пишете на Rust — значит Cargo.toml, развёртываете в Kubernetes — значит YAML, создаёте расширение VS Code — значит JSONC. Только в новом проекте без ограничений экосистемы вопрос «что приятнее писать» действительно актуален.
8. Границы конвертации
| Направление | Информация, которая всегда теряется | Совет |
|---|---|---|
| JSON → TOML | null, массивы верхнего уровня, ключи, которые невозможно выразить |
Сначала нормализуйте структуру и отбросьте пустые поля |
| TOML → JSON | Комментарии, типы дат, inf / nan |
Конвертируйте даты в строки RFC 3339 |
| YAML → JSON | Комментарии, якоря и ключи слияния, теги, несколько документов | Сначала разверните якоря, затем конвертируйте документ за документом |
| JSON → YAML | Структурных потерь нет, но строки дат могут автоматически разбираться | Заключайте строки дат в кавычки |
| CSON → JSON | Комментарии, выражения CoffeeScript | Мигрируйте один раз; не синхронизируйте в обоих направлениях |
Инструменты конвертации гарантируют значения, но никогда не комментарии. Поэтому не проектируйте двунаправленный конвейер, где «JSON — источник, а YAML — артефакт сборки». Либо генерируйте только в одном направлении, либо поддерживайте один исходный файл.
9. Контрольный список
- [ ] Документируйте, какие типы файлов используют какой формат, и перечислите разрешённые диалекты;
- [ ] Предпочитайте TOML или YAML для конфигурации, поддерживаемой людьми, и JSON для машинного обмена;
- [ ] Храните даты в JSON как строки RFC 3339 и отмечайте формат в схеме;
- [ ] Представляйте деньги и целые выше
2^53как строки или минорные единицы, никогда как числа с плавающей точкой; - [ ] Валидируйте каждый формат в CI его собственным парсером, никогда не через
JSON.parseдля YAML; - [ ] Мигрируйте форматы только в одном направлении и удаляйте старый файл, чтобы они не могли дрейфовать.
Вопросы и ответы
Почему конвертация JSON в TOML падает на некоторых полях?
В TOML нет null, а корень документа TOML — таблица, поэтому поле null в JSON нужно удалить или заменить пустой строкой или сигнальным значением, а массив верхнего уровня нужно обернуть как {"items": [...]}. Комментарии, типы дат и inf/nan также теряются при движении в обратном направлении, поэтому конвертация должна быть односторонней.
Стоит ли держать два конфигурационных файла в разных форматах?
Нет. Инструменты конвертации гарантируют значения, но никогда комментарии, поэтому конвейер, где «JSON — источник, а YAML — артефакт сборки», будет дрейфовать. Либо генерируйте только в одном направлении, либо поддерживайте один исходный файл и удаляйте старый после миграции.
Как добавить комментарии в конфигурационный файл JSON?
В стандартном JSON нет комментариев. Вы можете перейти на JSONC (диалект VS Code, читаемый через jsonc-parser), держать sidecar-документ, объясняющий каждое поле, или перейти на TOML или YAML. Файлы, отправляемые в другие системы, должны оставаться стандартным JSON, а объяснения жить в документации или схеме.
TOML или YAML лучше для конфигурации приложения?
Выбирайте TOML, когда структура плоская, в основном пары ключ-значение, и важны нативные даты; его семантика более предсказуема, а различия парсеров меньше. Выбирайте YAML, когда нужны глубокая вложенность, несколько документов, переиспользование якорей или когда целевая экосистема YAML-первая, например Kubernetes или CI. Оба поддерживают комментарии, поэтому настоящий дифференциатор — структурная сложность и привязка к экосистеме.
Почему NO превращается в false в YAML?
YAML 1.1 трактует yes, no, on, off, y и n как булевы, поэтому код страны Норвегии NO разбирается как false. Это «проблема Норвегии». Избегайте её, используя реализацию, следующую YAML 1.2, или заключая в кавычки каждую строку, которую можно неверно истолковать.
Стоит ли ещё использовать CSON?
Не для новых проектов. CSON зависит от экосистемы CoffeeScript, имеет мало поддерживаемых инструментов и ограниченную поддержку редакторов и CI; после прекращения поддержки Atom его случаи использования сократились ещё больше. Если у проекта уже есть конфигурация CSON, запланируйте разовую миграцию на JSON, TOML или YAML, а не добавляйте ещё.