JSON Toolkit

Яку структуру має використовувати відповідь API

Головне: Голі обʼєкти чисті, доки не потрібні метадані; повні обгортки безпечні, але багатослівні. Для більшості проєктів використовуйте статус HTTP для результатів і стабільну обгортку для даних.

Середній~4 хв читанняОпубліковано 2026-10-30Оновлено 2026-10-30
Три форми відповіді API та їхні компроміси

Коротко: виражайте результати кодами статусу 4xx/5xx, тримайте навантаження в { "data": ..., "meta": ... } і перемикайтеся на обгортку error у разі збою; цього достатньо для внутрішніх API, і лише публічні платформи з багатьма інтеграторами потребують JSON:API чи OpenAPI.

Спершу відкиньте найгірший варіант: завжди повертати 200 із результатом у полі code.

Три форми

A. Голий обʼєкт

{ "id": 1, "name": "demo", "price": 99 }

Чисто, і семантика HTTP робить роботу (404 — це 404). Але щойно потрібна пагінація, попередження чи id трасування, нема куди їх подіти без зміни контракту.

B. Стабільна обгортка

{
  "data": { "id": 1, "name": "demo" },
  "meta": { "requestId": "abc", "took": 12 }
}

Навантаження й метадані живуть окремо, тож нові метадані ніколи не переформовують data. Коштує одного рівня вкладеності.

C. Обгортка на все (уникайте)

{ "code": 0, "message": "success", "data": {...} }

Форма не гріх; гріх — практика. Статус 200 для кожного результату означає, що CDN, шлюзи, автоматичні вимикачі, політики повторів і дашборди всі бачать успіх. Кожна тривога тоді потребує власного розбору.

Рекомендація

Статус HTTP для результату, обгортка для навантаження.

{
  "data": { "id": 1, "name": "demo" },
  "meta": { "requestId": "req_8f2a", "took": 12 }
}
{
  "error": {
    "code": "ORDER_NOT_FOUND",
    "message": "Order does not exist or was deleted",
    "details": [{ "field": "id", "issue": "not_found" }]
  },
  "meta": { "requestId": "req_8f2a" }
}

Статус 4xx або 5xx; code стабільний і машинозчитуваний; message для людей; details для помилок форми на рівні полів.

Жорсткі правила

  1. Кінцеві точки списків мусять нести метадані пагінації. Без total чи курсора немає пейджера.
  2. Порожні списки повертають [], ніколи null. null.map — повторюваний збій.
  3. Часові мітки в ISO 8601 зі зміщенням. Дивіться який формат для часових міток.
  4. Одна конвенція найменування. snake_case або camelCase, конвертована один раз на межі.
  5. Гроші як цілі дрібні одиниці або рядки. 99.99 не точне в двійковій плаваючій точці.
  6. Не змішуйте null з відсутністю. Дивіться null чи пропустити поле.

Коли впроваджувати специфікацію

  • Публічні платформи з багатьма інтеграторами: JSON:API або OpenAPI плюс спільна обгортка
  • Внутрішні API однієї команди: обгортки вище достатньо
  • Сильні контракти: спершу Schema, структури генеруються з неї

Специфікації заощаджують обговорення й коштують онбордингу. Для команди з пʼяти людей JSON:API зазвичай робота з відʼємним результатом.

Часті питання

Як обирати між голим обʼєктом і обгорткою?

Використовуйте обгортку, коли потрібні пагінація, попередження чи requestId, щоб meta могла рости, не переформовуючи data. Повертайте голий обʼєкт, лише коли метадані не потрібні й ви приймаєте, що додавання полів пізніше змінить контракт.

Чому API ніколи не має повертати 200 для кожного результату?

CDN, шлюзи, автоматичні вимикачі, політики повторів і дашборди всі читають статус HTTP, щоб вирішити, кешувати, повторювати чи піднімати тривогу. З 200 усюди вони трактують збої як успіхи, і кожна тривога потребує власного розбору бізнес-коду.

Чи мають кінцеві точки списків нести метадані пагінації?

Так. Без total чи курсора немає пейджера, а порожні списки мусять повертати [], а не null, інакше виклик .map на фронтенді ламається.

Додаткове читання