JSON Toolkit

JSON, TOML, YAML или CSON: выбор формата конфигурации

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

Начинающий~9 мин чтенияОпубликовано 2026-10-31Обновлено 2026-10-31
Обложка, сравнивающая форматы конфигурации 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.

Есть четыре практических пути, по степени инвазивности:

  1. Перейти на JSONC — это стандартный JSON плюс комментарии и висячие запятые. Его используют settings.json и tsconfig.json в VS Code. Цена — читатель должен использовать парсер, понимающий комментарии, например jsonc-parser; обычный JSON.parse падает. Подробности в JSON5 и JSONC: JSON с комментариями.
  2. Держите sidecar-документ. config.json остаётся машиночитаемым, а config.md объясняет, что означает каждое поле и почему оно имеет такое значение. Оба живут в одном каталоге и меняются в одном коммите.
  3. Поместите объяснения в схему. Ключевые слова description и $comment в JSON Schema могут документировать поля, но схемы редко поставляются вместе с конфигурацией во время выполнения, поэтому человек, читающий конфигурацию, может никогда их не увидеть.
  4. Перейдите на 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, а не добавляйте ещё.