Дуглас Крокфорд и JSON: минимум, ставший языком API
Разбираем роль Дугласа Крокфорда и почему JSON стал стандартом обмена данными между фронтендом, бэкендом и API. Практики, ошибки и безопасность.

Что такое JSON и почему о нём говорят в каждом проекте
JSON (JavaScript Object Notation) — это текстовый формат для представления данных: чисел, строк, булевых значений, списков и объектов «ключ–значение». Его читают и люди, и программы, а главное — его легко отправлять по сети и хранить в логах.
Почему JSON называют «минимальным»
Минимальность JSON в том, что в нём нет «лишних» возможностей: никаких комментариев, ссылок, дат как отдельного типа, бинарных блоков или сложных схем прямо внутри формата. Есть небольшой набор правил и типов, которых хватает для большинства прикладных данных.
Плюс JSON специально ограничивает неоднозначности. Например, строка всегда в двойных кавычках, а ключи объектов — только строки. За счёт этого разные языки и библиотеки обычно интерпретируют один и тот же документ одинаково.
Почему он стал общим языком между частями системы
В типичном продукте фронтенд, бэкенд, мобильные клиенты, интеграции и аналитика написаны на разных технологиях. JSON стал «нейтральным» способом договориться, как выглядят запрос и ответ API:
- фронтенд отправляет данные формы в JSON;
- бэкенд отвечает JSON-объектом;
- сервисы между собой обмениваются тем же форматом;
- логи и события (например, для аналитики) часто тоже сериализуются в JSON.
Отсюда и ощущение, что JSON «везде»: он живёт на стыках компонентов, где больше всего риск недопонимания.
Какие вопросы разберём дальше
Дальше пройдём путь от истории появления формата и роли Дугласа Крокфорда до практики: как проектировать модели, предотвращать типовые ошибки, валидировать данные, думать о безопасности и аккуратно эволюционировать API без поломок для клиентов.
Кому это полезно
Материал пригодится:
- продактам и аналитикам — чтобы читать и обсуждать контракты API;
- техписателям — чтобы описывать поля и ограничения;
- разработчикам — чтобы избегать несовместимостей, неожиданных парсинг-ошибок и «магии» в данных.
Дуглас Крокфорд: человек, который сделал JSON известным
Дуглас Крокфорд — инженер и популяризатор идей, который сильно повлиял на то, как мир воспринимает JSON. Важно аккуратно формулировать его вклад: он не «в одиночку изобрёл формат из ничего», но именно он помог превратить удобный приём обмена данными в общепринятое правило игры для API.
Популяризация и стандартизация без мифологии
Крокфорд одним из первых последовательно объяснил, почему простой текстовый формат лучше подходит для обмена данными между системами, чем тяжеловесные альтернативы. Он же закрепил понятные принципы: минимум сущностей, однозначный синтаксис, читаемость человеком и простота машинного разбора.
Дальше началась «официальная» часть истории: появились документы, которые фиксировали JSON как спецификацию (в частности, RFC 4627 и более поздние RFC 7159/8259, а также стандарт ECMA-404). Формально эти тексты — плод работы сообществ и организаций, но имя Крокфорда неразрывно связано с тем, что JSON был описан коротко, чётко и без лишних возможностей.
JavaScript-происхождение: плюс и источник путаницы
JSON вырос из синтаксиса JavaScript (объектные литералы), поэтому он выглядит знакомо фронтенд-разработчикам и легко «встраивается» в веб-экосистему. Но это же породило распространённую ошибку: думать, что «JSON — это просто JavaScript-объект». На практике JSON строже: меньше типов, нет комментариев, нет вычислений, нет ссылок на переменные.
Как «удобный формат» стал стандартом для API
Вклад Крокфорда удобно описывать так:
- он продвигал идею минимального и безопасного формата обмена;
- задал тон: лучше ограничить возможности, чем потом лечить несовместимость;
- помог сформировать консенсус, из которого вырос де-факто стандарт для API.
Эта история важна не как биография, а как урок: иногда именно минимализм и ясные ограничения делают технологию массовой.
Правила JSON: что разрешено и что ломает совместимость
JSON ценят за предсказуемость: если документ валиден, почти любая платформа сможет его разобрать одинаково. Эта «строгость» иногда раздражает, но именно она снижает количество сюрпризов при обмене данными между клиентом, сервером и сторонними интеграциями.
Минимальный набор типов
В JSON всего шесть типов значений — этого хватает для большинства API:
- object — набор пар
"ключ": значение - array — упорядоченный список значений
- string — строка
- number — число (целое или дробное)
- boolean —
true/false - null — отсутствие значения
Важно: JSON не знает отдельных типов вроде даты, байтов, undefined, NaN или Infinity. Всё это нужно договорённо представлять (например, дата как строка в ISO 8601).
Ключевые ограничения синтаксиса
Есть несколько правил, которые чаще всего ломают совместимость:
- Двойные кавычки обязательны для строк и ключей:
"name", а не'name'. - Комментариев нет — ни
//, ни/* ... */. Если хочется пояснений, заводят отдельные поля (например,"_comment"), но в публичных API лучше так не делать. - Запятые строго по месту: после последнего элемента массива или объекта запятая запрещена.
Почему строгий синтаксис помогает совместимости
JSON специально сделан таким, чтобы его могли одинаково реализовать разные языки и библиотеки. Чем меньше «вольностей», тем ниже шанс, что один парсер примет документ, а другой — упадёт или, хуже того, интерпретирует данные иначе. В API это напрямую влияет на стабильность клиентов и на поддержку.
Примеры «похожего, но не JSON»
{
'name': 'Alice', // одинарные кавычки и комментарий
"age": 30,
}
[1, 2, 3,]
Оба примера часто встречаются в конфигурациях (например, в JavaScript-объектах), но это не JSON. Для обмена данными по сети держитесь строгого формата — так меньше неожиданностей в продакшене.
Почему JSON стал универсальным языком между фронтом и бэком
JSON победил не потому, что «самый мощный», а потому что почти везде одинаково понятен. Он достаточно простой для чтения глазами и достаточно строгий, чтобы машины могли уверенно обмениваться данными.
Почему фронтенду удобно
На фронте JSON ощущается как «родной»: в JavaScript объекты и массивы выглядят почти так же, а JSON.parse() и JSON.stringify() есть из коробки. В TypeScript поверх этого легко накинуть типы, автодополнение и проверку полей на этапе разработки. В итоге меньше ручной возни с преобразованиями и меньше несостыковок между тем, что пришло по сети, и тем, что ожидает UI.
Почему бэкенду удобно
На стороне сервера JSON давно стал стандартной опцией: практически любой язык и фреймворк умеют сериализовать структуры в JSON и обратно. Это снижает стоимость интеграций: не нужно договариваться о «своём» формате, писать специфичные парсеры или поддерживать экзотические кодеки. Даже если сервисы написаны на разных языках, JSON остаётся общей точкой встречи.
Почему удобно API
Для API JSON хорош сочетанием читаемости и предсказуемости. Структуры «объект–поля» легко документировать, тестировать и логировать. Плюс он отлично ложится на HTTP: ответы можно кэшировать на уровне клиентов и прокси, а изменения удобно отслеживать по схеме и контрактам (подробнее — в разделе про JSON Schema).
Роль JSON в микросервисах и интеграциях
В микросервисной архитектуре и при подключении внешних систем JSON часто становится «общим знаменателем»: им обмениваются очереди, вебхуки, внутренние API и партнёрские интеграции. Даже когда внутри компании есть другие форматы, JSON остаётся универсальным «языком на границе» — там, где важнее всего совместимость и скорость подключения нового участника.
Проектирование JSON-моделей: соглашения, которые экономят недели
JSON часто кажется «самоочевидным»: взяли объект, отправили, прочитали. На практике же большую часть времени съедают не парсинг JSON и не сериализация, а мелкие несогласованности в форме и смысле полей. Пара простых договорённостей заранее экономит недели на правках клиентов и поддержке API.
Кстати, такие договорённости удобно фиксировать сразу при прототипировании: например, в TakProsto.AI можно в диалоге описать сущности и правила API, получить черновики структур запросов/ответов и затем превратить их в схему и тесты — без лишней ручной рутины.
Объект vs массив: как выбирать форму ответа API
Правило простое: ресурс — объект, коллекция — массив объектов. Если endpoint возвращает «список чего‑то», делайте обёртку-объект с массивом внутри, чтобы было куда добавлять метаданные (пагинацию, итоги) без поломок:
{ "items": [ {"id": "1"} ], "total": 1 }
Голый массив ([ ... ]) удобен, но хуже расширяется.
Именование полей: camelCase/snake_case и единый стиль в проекте
Выберите один стиль и зафиксируйте его в гайде. Для JSON в API часто берут camelCase (особенно если клиенты на JS), но snake_case тоже нормален, если он везде одинаковый. Важнее другое: не смешивать userId и user_id в одном продукте и не переименовывать поля «по вкусу» между сервисами.
Числа и деньги: риски float, когда хранить как строку
JSON-числа не различают int/decimal, а клиенты могут по-разному обрабатывать дроби. Для денег безопаснее:
- хранить сумму в минимальных единицах (например,
amountMinor: 1990для 19.90) - или передавать строкой (
"19.90"), если важна точность отображения
Дата и время: ISO 8601, часовые пояса, соглашения
Договоритесь: даты и время — ISO 8601. Для событий используйте timezone-однозначный формат, чаще всего UTC:
{ "createdAt": "2025-12-26T10:15:00Z" }
Если нужен локальный часовой пояс — передавайте его явно, не «угадывайте».
null vs отсутствие поля: как договориться и не путать клиентов
Отсутствие поля обычно означает «не знаем/не применимо/не отдаём», а null — «значение намеренно пустое». Выберите семантику и следуйте ей.
Хорошая практика: не отправлять необязательные поля, а null использовать только когда это действительно отдельное состояние, с которым клиент должен считаться.
Как JSON проходит по системе: от объекта в коде до сети и обратно
Когда вы «отдаёте JSON» из API, по факту вы запускаете цепочку преобразований. На одном конце — объект в памяти программы, на другом — набор байтов, который путешествует по сети, а затем снова превращается в объект у клиента.
Сериализация и десериализация: что происходит «под капотом»
На сервере структура данных (словарь, объект, массив) сериализуется: библиотека строит текст JSON, соблюдая правила кавычек, запятых и типов. Затем этот текст кодируется в байты (почти всегда UTF-8) и отправляется как тело HTTP-ответа.
На клиенте путь обратный: байты декодируются в строку, затем парсер JSON строит из неё структуру данных. Важно помнить: JSON — это только числа, строки, булевы значения, null, массивы и объекты. Даты, деньги, большие целые, бинарные данные — всё это вы представляете договорённостями (например, ISO-строкой для дат).
Кодировки и экранирование строк
Большинство проблем со «странными символами» — не про JSON, а про несовпадение кодировки или некорректное экранирование. Критичные случаи:
- переносы строк, кавычки и обратные слэши внутри строк должны быть экранированы
- управляющие символы и неожиданные невидимые символы ломают парсинг
- всегда фиксируйте UTF-8 и корректный
Content-Typeна ответах
Большие ответы: payload, компрессия, пагинация
Чем больше JSON, тем дольше сериализация, передача и парсинг. Обычно выигрывают три практики: компрессия на уровне HTTP, пагинация списков и сдержанность в полях (не отдавать «всё на всякий случай»).
Стриминг и частичная загрузка
Если данные огромные или их нужно показывать сразу, JSON может стать узким местом: он требует полноценного текста для удобного парсинга. Тогда помогают постраничная выдача, частичные ответы (например, параметры fields) или стриминговые протоколы/форматы, где запись идёт по элементам.
Клиентская типизация: меньше any и сюрпризов
Главная защита от неожиданных полей и «плавающих» типов — строгая типизация на клиенте и проверка структуры данных на входе. Чем раньше вы превращаете «сырой JSON» в типизированную модель (и отклоняете несовместимое), тем меньше багов уезжает в интерфейс.
JSON Schema и контрактный подход: меньше сюрпризов в API
Когда API использует JSON «по договорённости», проблемы начинаются там, где ожидания расходятся: поле внезапно становится числом вместо строки, появляется новый статус, а клиент падает в самом неожиданном месте. JSON Schema помогает зафиксировать контракт: что именно можно прислать и что гарантированно можно получить.
Основные идеи JSON Schema
Схема описывает структуру данных и правила, по которым они валидны. На практике чаще всего используются:
- type: строка, число, объект, массив и т.д.
- required: какие поля обязательны
- enum: допустимые значения (например, статусы)
- format: дополнительные ограничения для строк (email, date-time, uri)
Пример упрощённой схемы ответа:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "status"],
"properties": {
"id": {"type": "string"},
"status": {"type": "string", "enum": ["new", "paid", "canceled"]},
"createdAt": {"type": "string", "format": "date-time"}
},
"additionalProperties": false
}
Контракты между командами
Контрактный подход полезен, когда фронт, бэк и мобильные клиенты развиваются параллельно. Схема становится «единой точкой правды»: её обсуждают в ревью, по ней договариваются о правилах обратной совместимости, её используют в тестах.
Документация и валидация
Из схем удобно генерировать документацию и примеры. Ещё важнее — валидировать входящие данные на сервере: это снижает число «странных» багов и упрощает диагностику. Клиентам тоже полезно валидировать критичные ответы, чтобы быстрее находить изменения контракта.
Версионирование схем: изменения без поломок
Хорошее правило: добавляйте новое как необязательное, избегайте переименований и смены типов, а enum расширяйте осторожно. Сами схемы версионируйте рядом с кодом и фиксируйте изменения в changelog; подробнее про подходы — в /blog/api-versioning.
Границы применимости
Schema особенно помогает для публичных API и сложных моделей. Но она может усложнить жизнь, если модель часто меняется и нет дисциплины поддерживать схемы. Тогда начните с малого: валидируйте ключевые запросы/ответы и постепенно расширяйте покрытие.
Типовые ошибки при работе с JSON и как их предотвращать
JSON выглядит простым, поэтому ошибки чаще всего не «громкие», а коварные: данные проходят, но смысл меняется. В итоге баги проявляются на аналитике, оплатах или в редких ветках интерфейса — и их трудно воспроизвести.
Неявные преобразования типов: «строки вместо чисел»
Самая частая проблема — когда число приезжает строкой: "10" вместо 10. На фронте это может незаметно работать (сравнение, конкатенация), а на бэке — ломать сортировки, расчёты и валидацию.
Как предотвращать:
- Явно фиксируйте типы в контракте (например, через JSON Schema) и валидируйте на входе.
- Не «чините» типы молча: если поле должно быть числом — возвращайте понятную ошибку.
Несогласованность null и пустых значений
null, пустая строка "", пустой массив [] и отсутствие ключа — это разные состояния. Когда один сервис отправляет null, второй ожидает отсутствие поля, а третий трактует null как «удалить значение», получаются трудноуловимые расхождения.
Как предотвращать:
- Договоритесь о семантике: что означает отсутствие поля, а что —
null. - Для опциональных полей чаще выбирают: «нет ключа» вместо
null(или наоборот) — главное, чтобы единообразно.
Ломающее переименование полей и удаление ключей
Переименовать userId в id кажется безобидным, но для клиентов это «поломка». То же касается удаления «редко используемого» поля: оно может быть критичным для отдельных интеграций.
Профилактика:
- Добавляйте новые поля, не удаляя старые сразу.
- Используйте период устаревания: помечайте поле как deprecated и удаляйте только по плану.
«Почти JSON» в логах и конфигурациях
Частая причина ошибок парсинга — формат, похожий на JSON, но не JSON: одинарные кавычки, комментарии, хвостовые запятые, неэкранированные переносы строк.
Решение простое: храните данные в валидном JSON и проверяйте их валидатором в CI; для конфигураций, где нужны комментарии, выбирайте формат, который их поддерживает.
Практика: чек-лист ревью JSON-ответов
Перед тем как «отпустить» ответ API:
- Все типы стабильны (числа — числа, булевы — булевы).
null/пусто/нет ключа используются по договорённости.- Поля не переименованы и не удалены без миграционного плана.
- Примеры в документации совпадают с реальными ответами.
- Ошибки возвращаются структурировано и предсказуемо (код, сообщение, детали).
Безопасность JSON: валидация, лимиты и аккуратные ошибки
JSON часто воспринимают как «безопасный текст», но на практике риски возникают не из-за формата, а из-за того, как его принимают, парсят и используют дальше. Хорошая новость: большинство проблем решается простыми ограничениями и дисциплиной.
Чем опасен «неограниченный» вход
Если API принимает любой JSON без лимитов, атакующий может устроить отказ в обслуживании: отправить гигантское тело запроса, очень глубокую вложенность или массивы на миллионы элементов. Даже без «взлома» это легко перегружает память, CPU и очередь запросов.
Отдельная категория — рекурсия и глубина: объект вида {\"a\":{\"a\":{\"a\":...}}} может заставить парсер или вашу бизнес-логику упереться в лимиты стека или тратить время на обход структуры.
Валидация и лимиты: что фиксировать заранее
Минимальный набор ограничений, который стоит договорить на уровне сервиса:
- Размер тела: ограничение на
Content-Lengthи фактический размер при чтении (например, 1–2 МБ для публичных endpoints). - Глубина: максимальная вложенность объектов/массивов (например, 20–50).
- Размер массивов: верхняя граница количества элементов.
- Длины строк: особенно для полей вроде комментариев, названий, токенов.
Валидацию лучше делать по схеме (например, JSON Schema) или хотя бы ручными проверками типов и обязательных полей — до того, как данные попадут в БД или очередь. Если у вас уже есть схемы, логично сослаться на /blog/json-schema.
Инъекции: где реальный риск
Сам JSON редко является «инъекцией», но становится источником опасных строк:
- Логи: подмена строк, «разрыв» формата логов, внедрение управляющих символов. Решение: структурированные логи и экранирование.
- Шаблоны/HTML: XSS при отображении полей из JSON. Решение: контекстное экранирование, запрет «сырых» вставок.
- SQL/поисковые запросы: риск появляется, если вы собираете запрос строкой. Решение: параметризация и whitelist полей для фильтров.
Безопасная обработка и аккуратные ошибки
Используйте строгий JSON-парсер и избегайте любых eval-подходов (включая «почти JSON» с комментариями или хвостовыми запятыми), если данные приходят извне.
Ошибки возвращайте так, чтобы клиент мог исправиться, но без утечек: код ошибки, понятное сообщение, путь до поля (например, "path": "user.email"). Не включайте в ответы стек-трейсы, внутренние идентификаторы, сырой запрос или детали БД — это лучше оставлять только во внутренних логах.
Эволюция API на JSON: версионирование без боли для клиентов
JSON удобен тем, что его легко расширять. Но именно из‑за этой «лёгкости» API часто меняют без плана — и клиенты внезапно получают ошибки в продакшене. Ниже — практичные подходы, которые помогают развивать JSON‑API предсказуемо.
Стратегии версионирования
-
Версия в URL:
/api/v1/orders. Плюс — прозрачно и просто для поддержки. Минус — при частых изменениях плодит параллельные ветки. -
Версия в заголовках (например,
Accept: application/vnd.company.orders+json;version=2). Плюс — URL остаётся чистым. Минус — сложнее отлаживать и документировать. -
Версия в payload (
{"version":2, ...}) — уместно для событий/вебхуков и интеграций, где payload живёт дольше запроса. Для обычного REST это чаще лишняя нагрузка.
Backwards-compatible изменения
Цель — чтобы старые клиенты продолжали работать без обновления.
- Добавляйте новые поля, не меняя смысл старых. Клиенты должны игнорировать неизвестные поля.
- Расширяйте enum аккуратно: новые значения допустимы только если клиенты не «падают» на неизвестных. Лучше предусмотреть поведение по умолчанию (
"unknown","other"). - Не делайте поле обязательным внезапно: сначала вводите как необязательное, затем — после периода деприкации.
Breaking changes: план, объявление, миграция
Ломающие изменения — это переименование/удаление полей, смена типов (string → object), изменение семантики значений.
Практика: сначала выпускайте новую версию (v2) или новый ресурс, параллельно поддерживая старый, и дайте понятный путь миграции: что меняется, примеры запросов/ответов, типичные ловушки.
Деприкация: сроки, метрики, коммуникация
Заранее задайте правило: например, «деприкация минимум 90 дней». Отслеживайте использование по логам/ключам клиента: сколько запросов приходит на v1, какие методы ещё живые. Коммуникация должна быть многоканальной: release notes, уведомления в ответах (например, заголовок Deprecation), письмо интеграторам.
Минимальный набор правил стабильного публичного API
- Не удалять и не переименовывать поля без версии.
- Новые поля — только необязательные.
- Enum расширять с безопасным поведением на неизвестных значениях.
- Ошибки возвращать в одном формате и без «сюрпризов».
- У каждой версии — срок жизни и понятная политика поддержки.
Альтернативы JSON: когда стоит выбрать другой формат
JSON — отличный «по умолчанию», но не единственный вариант. Если формат данных начинает влиять на скорость разработки, производительность или качество интеграций, стоит осознанно сравнить альтернативы.
XML и YAML: где сильнее, где слабее
XML выигрывает там, где нужна богатая экосистема вокруг схем, пространств имён и сложных документов (например, в наследуемых корпоративных стандартах). Но он многословный: больше трафика, больше «шума» в диффах и выше шанс ошибиться в разметке.
YAML часто приятнее читать человеку, особенно в конфигурациях. Но у YAML больше «магии»: пробелы, неоднозначности и особенности парсеров могут давать неожиданные результаты. JSON строже: меньше вариантов трактовки — выше предсказуемость в интеграциях.
Когда лучше бинарные форматы (например, protobuf)
Если вы упираетесь в размер и скорость, бинарные форматы вроде Protocol Buffers, Avro или MessagePack часто эффективнее: меньше байт по сети, быстрее (де)сериализация, чётче контракты. Это заметно в мобильных сетях, стриминге событий и внутреннем межсервисном обмене с высоким QPS.
Когда JSON остаётся лучшим выбором
Для публичных API, веба и интеграций с большим числом клиентов JSON почти всегда проще: он поддерживается везде, легко дебажится, прозрачен в логах и инструментах (curl, Postman), а ошибки проще объяснять пользователям.
Гибридный подход
Практичный компромисс: JSON наружу, бинарный формат внутри. Например, внешний REST/HTTP API отдаёт JSON, а внутренние сервисы общаются protobuf/gRPC — экономите ресурсы, не усложняя жизнь внешним клиентам.
Критерии выбора формата
Выбирайте по нескольким вопросам: кто ваши клиенты (браузер, мобильные, партнёры), нужен ли человекочитаемый обмен, есть ли строгая схема и версионирование, насколько важны задержки и трафик, и как вы будете тестировать и отлаживать интеграции.
Практический чек-лист: как сделать JSON в продукте предсказуемым
Предсказуемый JSON — это не «красивые примеры в документации», а набор договорённостей и проверок, которые делают API стабильным для клиентов и удобным для поддержки внутри команды.
Чек-лист договорённостей для команды
- Стиль именования: выберите одно (например,
snake_caseилиcamelCase) и не смешивайте. Зафиксируйте для полей, параметров и ключей ошибок. - Типы полей: каждое поле должно иметь понятный тип и ограничения (строка/число/булево/массив/объект). Избегайте «то строка, то число».
- Даты и время: используйте ISO 8601 в UTC, например
2025-12-26T10:15:30Z. Не передавайте «человеческие» форматы вроде26.12.2025. - Ошибки: единый формат ответа об ошибке (например,
code,message,details,request_id) и стабильные коды ошибок. null: договоритесь, когда допустимnull, а когда поле лучше не возвращать. Главное — единообразие.- Пагинация: единый подход (limit/offset или cursor). Для cursor-пагинации фиксируйте поля:
items,next_cursor,has_more.
Инструменты процесса: чтобы правила соблюдались автоматически
Хорошие правила не должны «жить в голове».
- Линтеры и автоформатирование: настройте форматирование JSON и проверки стиля в репозитории, чтобы любой PR приводил JSON к единому виду.
- Контрактные тесты: проверяйте, что бэкенд действительно отдаёт ответы по контракту, а фронт/клиенты корректно их понимают.
- Валидация на границе: входящие запросы валидируйте до бизнес-логики, а исходящие ответы — хотя бы на уровне ключевых инвариантов.
Если вы делаете сервис «с нуля» и хотите быстро прийти к дисциплине контрактов, TakProsto.AI можно использовать как ускоритель: описать в чате сущности, endpoints и правила (типы, required, enum), а затем итеративно довести JSON-модели до стабильного контракта, сохраняя историю изменений через снапшоты и откаты.
Документация, которой можно доверять
Документация полезна, когда она проверяется реальностью.
- Приводите реальные примеры запросов/ответов, включая «пустые» и пограничные случаи.
- Для каждого эндпоинта перечисляйте коды ошибок и условия их появления.
- Поддерживайте «минимальный» и «расширенный» пример, чтобы было ясно, какие поля обязательны.
Что улучшить в текущем API уже на этой неделе
Сделайте небольшой аудит: выберите 5–10 самых используемых эндпоинтов и проверьте консистентность типов, дат, null, структуры ошибок и пагинации. Затем согласуйте контракт с командой и закрепите его тестами.
Если нужно больше практических материалов — смотрите другие заметки в /blog. Для тем про контракты и схемы удобно начать с /blog/json-schema.
FAQ
Что такое JSON и для чего он нужен в проектах?
JSON — это текстовый формат обмена данными: объекты (пары «ключ–значение»), массивы, строки, числа, булевы значения и null.
Его выбирают, потому что он:
- легко читается человеком;
- одинаково поддерживается почти на всех платформах;
- хорошо подходит для HTTP API, логов и событий.
Чем JSON отличается от «просто JavaScript-объекта»?
Он выглядит похоже на объектные литералы JavaScript, но JSON строже.
В JSON нельзя:
- использовать комментарии (
//,/* ... */); - писать строки и ключи в одинарных кавычках;
- ставить «хвостовые» запятые.
Идея в том, чтобы один и тот же документ одинаково парсился в разных языках.
Какую роль сыграл Дуглас Крокфорд в истории JSON?
Его вклад — прежде всего в популяризацию и формулировку принципов: минимальный набор типов, однозначный синтаксис, простота разбора.
Стандарты JSON закреплялись сообществом и организациями (RFC/ECMA), но именно благодаря этой «минималистичной» философии формат стал де-факто стандартом для API.
Почему JSON стал «общим языком» между фронтендом и бэкендом?
Потому что на стыках компонентов важнее всего предсказуемость: фронтенд, бэкенд, мобильные клиенты и интеграции могут быть на разных технологиях, а JSON понимают почти все.
Практически это означает:
- проще описывать запросы/ответы;
- легче отлаживать (человекочитаемый текст);
- меньше затрат на подключение новых клиентов и партнёров.
Что лучше для API: возвращать массив или объект с массивом?
Базовое правило: ресурс — объект, коллекция — массив объектов, но лучше возвращать коллекции в обёртке-объекте.
Например:
{ "items": [{"id":"1"}], "total": 1 }
Так вы сможете добавить пагинацию и метаданные без ломания контракта.
Как правильно передавать даты и время в JSON?
Следуйте двум практикам:
- фиксируйте формат в ISO 8601;
- для событий используйте UTC с
Z.
Пример:
{ "createdAt": "2025-12-26T10:15:00Z" }
Если нужен локальный часовой пояс — передавайте его явно, не заставляйте клиента «угадывать».
Как безопасно передавать деньги и числа с точностью в JSON?
Числа в JSON не разделяются на int/decimal, а клиенты могут по-разному обрабатывать дроби.
Для денег обычно выбирают одно из двух:
- минимальные единицы:
amountMinor: 1990(то есть 19.90); - строка для точности отображения:
"19.90".
Главное — закрепить подход в контракте и не смешивать варианты.
В чём разница между null и отсутствием поля в JSON?
Это разные состояния, и их нужно договорённо разделять:
- нет ключа: поле не применимо/не отдаётся/неизвестно;
null: намеренно «пустое» значение как отдельное состояние;- пустая строка/массив: значение задано, но пустое.
Хорошая практика для API: необязательные поля чаще не возвращать, а null использовать только когда это важно для логики клиента.
Какие меры безопасности важны при приёме JSON в API?
Минимальный набор мер:
- лимит на размер тела запроса (и фактическое чтение), например 1–2 МБ для публичных endpoint’ов;
- ограничение глубины вложенности и размера массивов;
- лимиты длины строк для «свободных» полей;
- валидация входа (по JSON Schema или ручными проверками) до бизнес-логики.
Ошибки отдавайте структурировано (код, сообщение, путь до поля), но без утечек внутренних деталей.
Как менять JSON-API без поломок для клиентов?
Ломающими считаются: переименование/удаление полей, смена типа, изменение смысла значений.
Чтобы эволюционировать без боли:
- добавляйте новые поля как необязательные;
- не делайте внезапно обязательными существующие поля;
- расширяйте
enumтак, чтобы клиенты не падали на неизвестных значениях; - для крупных изменений используйте версионирование и план миграции.
Полезно закреплять контракт схемами и тестами; про подходы — в /blog/api-versioning.