IlmHamroh
JavaScript Full-stack/25-qism. HTTP, Express va REST API28/51-dars17 daqiqa
Mundarija (31)

API dizayn konvensiyalari: nomlash, ISO 8601 sana, ID, null, enum va pul — Google AIP va Zalando

Qisqacha: Yaxshi API'ni mayda qarorlar izchilligi yaratadi. Maydon nomlari bitta uslubda (camelCase yoki snake_case), resurslar ko'plikda, sana — ISO 8601 UTC (2026-10-24T05:24:13.924Z). Pul — butun son eng kichik birlikda (tiyin) + valyuta kodi; katta ID va enum — satr; "qiymat yo'q" va null farqi aniq. Bu qarorlarni har safar qaytadan o'ylamaslik uchun Google (AIP), Microsoft va Zalando ochiq qo'llanmalar chiqargan. Jamoa ulardan birini asos qilib oladi va o'z qarorlarini API.md da yozadi.

Bu darsda

  • Katta kompaniyalarning API qo'llanmalari nima uchun kerakligini va qayerdan topishni bilasiz.
  • Nomlash, sana, ID, pul, enum, null bo'yicha konvensiya tanlay olasiz va sababini ayta olasiz.
  • JS'dagi ikki xavfli tuzoqni (2⁵³ dan katta ID, kasr pul) o'z ko'zingiz bilan ko'rasiz.
  • vazifalar-api uchun API.md — konvensiyalar, endpointlar, xatolar katalogi va changelog — yozib, holat 27 ni commit qilasiz.

Oldin bilishingiz kerak: REST prinsiplari va resurslar, Xato javoblari: Problem Details, API versiyalash va deprecation, Bulk va uzoq davom etuvchi operatsiyalar.

1. Nega bu kerak?

So'nggi o'nta darsda vazifalar-api ga ko'p narsa qo'shdik: sahifalash, xatolar, kesh, eksport. Har birida mayda qaror qabul qildik — maydon yaratildi mi yoki created_at? Sana qaysi formatda? ID son yoki satr? Bu qarorlar endi faqat kodda, tarqoq.

Yangi dasturchi — Sardor — jamoaga qo'shildi va yangi /v1/loyihalar endpointini yozdi. U created_at, "status": 2 va "deadline": "24.10.2026" ishlatdi. Kod ishlaydi. Lekin mijoz endi ikki xil sana formatini, ikki xil nomlash uslubini va "2 — qaysi holat ekan?" degan jumboqni hal qilishi kerak.

O'xshatish: shahar ko'chalaridagi belgilar. Har ko'chada o'z dizayner o'z belgisini o'ylab topsa — haydovchi har chorrahada to'xtab o'ylaydi. Yo'l harakati qoidalari bir xil belgilarni majburiy qiladi va haydovchi ularni o'qimaydi, taniydi. API konvensiyalari — dasturchilar uchun yo'l belgilari.

2. Mavjud qo'llanmalar

2.1 Uchta asosiy manba

Katta kompaniyalar minglab API'larni izchil saqlash uchun ichki qoidalarini ochiq e'lon qilgan:

Qo'llanma Kimniki Xususiyati
AIP (API Improvement Proposals) — google.aip.dev Google raqamlangan qoidalar: 122 — nomlar, 158 — sahifalash, 193 — xatolar
Microsoft REST API Guidelines — github.com/microsoft/api-guidelines Microsoft Azure va Graph API'lari uchun
Zalando RESTful API Guidelines — opensource.zalando.com/restful-api-guidelines Zalando MUST / SHOULD / MAY darajalari, juda aniq

Ular ko'p joyda bir xil, ba'zi joyda farq qiladi (masalan nomlash uslubi). Muhimi — bittasini tanlash va izchil bo'lish, "eng to'g'risini" topish emas.

2.2 Bu kursda nimani allaqachon qildik

Oldingi darslarning ko'p qarori shu qo'llanmalardan:

Mavzu Biz nima qildik Qaysi dars
resurs nomlari ot, ko'plik: /vazifalar REST prinsiplari
sahifalash limit, kursor, Link Pagination
xatolar RFC 9457 + barqaror kod Problem Details
versiya /v1, Deprecation/Sunset Versiyalash
uzoq ish 202 + holat resursi Bulk va LRO

Bu darsda qolgan mayda qarorlarni ko'ramiz va hammasini bitta hujjatga yig'amiz.

3. Nomlash

3.1 JSON maydonlari: camelCase yoki snake_case

Uslub Misol Kim tanlagan
camelCase yangilandi, createdAt Google (JSON'da), Microsoft, JS dunyosi
snake_case created_at Zalando (MUST), GitHub, Stripe, Twitter

JS mijozda camelCase qulay: vazifa.yaratildi — o'zgaruvchi nomi bilan bir xil. Python yoki Ruby jamoasi uchun snake_case tabiiy. Kanon camelCase tanladi — frontend (22-qism) shu nomlarni ishlatadi.

Ikki uslubni aralashtirish — eng yomon variant. Agar backend jadvallarida snake_case bo'lsa (Postgres'da ko'pincha shunday — 26-qism), aylantirish bitta joyda bo'ladi. Quyidagi toza funksiyalar brauzerda ham ishlaydi:

js
const toCamel = (s) =>
  s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
const toSnake = (s) =>
  s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);

function keysTo(convert, obj) {
  return Object.fromEntries(
    Object.entries(obj).map(([k, v]) => [convert(k), v]),
  );
}

const row = {
  id: 7, matn: "Non olish", yaratilgan_vaqt: "2026-10-24",
};
const json = keysTo(toCamel, row);
console.log(json);
console.log(keysTo(toSnake, json));

Konsolda:

text
{ id: 7, matn: 'Non olish', yaratilganVaqt: '2026-10-24' }
{ id: 7, matn: 'Non olish', yaratilgan_vaqt: '2026-10-24' }

Bu funksiyalar faqat birinchi darajani aylantiradi; ichma-ich obyektlar uchun rekursiya kerak (mashqda).

3.2 URL va query

  • Yo'l bo'laklari — kichik harf, ko'plik, so'zlar - bilan (kebab-case): /v1/vazifa-guruhlari. Kanonda: /v1/vazifalar, /v1/eksportlar.
  • Query parametrlar — maydonlar bilan bir xil uslubda: ?sort=-yaratildi&fields=matn.
  • Fe'l yo'q (/getVazifalar emas) — fe'l HTTP metodida. Istisno — "harakat" endpointlari (/vazifalar/toplam, Google'da :batchCreate): ular resurs emas, amal.

Tekshirib ko'ring: Sardorning yangi endpointi: GET /v1/getLoyihaList?page_size=10. Nechta konvensiya buzilgan?

Javob

Uchta. (1) Yo'lda fe'l get — metod allaqachon GET. (2) List va birlik Loyiha — resurs ko'plikda bo'lsin: /v1/loyihalar. (3) page_size — snake_case, API esa camelCase va sahifalash parametri allaqachon limit deb nomlangan. To'g'risi: GET /v1/loyihalar?limit=10.

4. Qiymat formatlari

4.1 Sana va vaqt — ISO 8601, UTC

Vaqt lahzasi — doim ISO 8601 (aniqrog'i RFC 3339 profili), UTC, Z bilan: "2026-10-24T05:24:13.924Z". Nega:

  • Matn — tartiblanadi: alifbo tartibi = vaqt tartibi.
  • Har tilda o'qiladi: JS new Date(s), Python datetime.fromisoformat(s).
  • Vaqt mintaqasi chalkashmaydi: Z — UTC. Toshkent vaqtiga aylantirish — faqat ko'rsatishda, mijozda (Date va vaqt zonalari).

Unix vaqt (1792800000) ham ishlaydi, lekin odam o'qiy olmaydi va "soniyami yoki millisekundmi?" degan savol tug'iladi. "24.10.2026" — umuman yo'q: kun va oy tartibi davlatga qarab farq qiladi.

Sana-vaqt emas, faqat kun kerak bo'lsa (tug'ilgan kun, muddat) — "2026-10-24", vaqtsiz. Kanondagi ?dan=2026-10-24 filtri shunday (backend'da sana va vaqt darsida chuqurroq).

4.2 ID — son yoki satr

JS'da son — 64-bitli kasr (double). U butun sonlarni faqat 2⁵³ − 1 gacha aniq saqlaydi. Undan katta ID JSON'dan o'qilganda jim buziladi. Bu blok brauzerda ham ishlaydi:

js
const big = '{"id": 9007199254740993, "idStr": "9007199254740993"}';
const parsed = JSON.parse(big);
console.log(parsed.id);
console.log(parsed.idStr);
console.log(Number.MAX_SAFE_INTEGER);

Konsolda:

text
9007199254740992
9007199254740993
9007199254740991

…993 → …992: oxirgi raqam o'zgardi, xato yo'q. Mijoz endi boshqa vazifani so'raydi. Twitter (hozir X) 2010-yilda 64-bitli ID'larga o'tganda aynan shu muammoga duch keldi: JSON javobga id bilan birga satr ko'rinishidagi id_str maydonini qo'shdi. X hujjati hozir ham kodda faqat satr ID ishlatishni tavsiya qiladi.

Google AIP ID'ni satr qilib berishni tavsiya qiladi. Kanon esa son qoldirdi (bosh muharrir qarori):

  • frontend (22-qism) z.int() kutadi — satrga o'tish buzuvchi o'zgarish bo'lardi;
  • Postgres identity ustuni (26-qism) 2⁵³ ga yaqinlashishi uchun milliardlab vazifa kerak.

Bu halol yozildi: API.md da "2⁵³ dan katta bo'lsa satrga o'tiladi — buzuvchi, v2". Yangi API boshlayotgan bo'lsangiz — satr ID tanlang (UUID, Snowflake), keyin o'zgartirish shart bo'lmaydi.

4.3 Pul — butun son, eng kichik birlikda

Pulni kasr son bilan saqlash — klassik xato:

js
console.log(0.1 + 0.2);
const priceTiyin = 3500000; // 35 000 so'm = 3 500 000 tiyin
const total = priceTiyin * 3 + 500000;
console.log(total, total / 100);

Konsolda:

text
0.30000000000000004
11000000 110000

Kasr sonlar ikkilik tizimda aniq ifodalanmaydi — 0.1 + 0.2 ≠ 0.3. Shuning uchun pul eng kichik birlikda butun son bilan beriladi (so'm uchun — tiyin, dollar uchun — sent) va valyuta kodi (ISO 4217) bilan:

json
{ "narx": { "summa": 3500000, "valyuta": "UZS" } }

Stripe aynan shunday qiladi (amount butun sonda, currency). O'zbekistonda Payme Merchant API ham amount ni tiyinda qabul qiladi (CreateTransaction hujjatiga ko'ra, 2026-10 holatida). Valyuta kodi doim yoniga qo'yiladi — "3500000" ning o'zi hech narsa demaydi.

Ko'rsatish — mijozda. Intl.NumberFormat natijasi Node va brauzerda farq qilishi mumkin (Intl darsi), shuning uchun bu misolda qo'lda formatlaymiz:

js
function formatSom(tiyin) {
  const som = Math.trunc(tiyin / 100);
  const rest = Math.abs(tiyin % 100);
  const groups = String(som).replace(/\B(?=(\d{3})+(?!\d))/g, " ");
  if (!rest) return `${groups} so'm`;
  return `${groups},${String(rest).padStart(2, "0")} so'm`;
}

console.log(formatSom(3500000));
console.log(formatSom(1250050));
console.log(formatSom(5));

Konsolda:

text
35 000 so'm
12 500,50 so'm
0,05 so'm

vazifalar-api da pul yo'q — lekin API.md da qoida yozilgan: kerak bo'lsa, shu shaklda.

4.4 Enum — satr

Enum (sanab o'tiladigan qiymat) — cheklangan ro'yxatdan biri: eksport holati kutilmoqda | bajarilmoqda | tayyor | xato. Son ("holat": 2) emas, satr:

  • o'qiladi — logda 2 nimaligini hech kim eslamaydi;
  • yangi qiymat qo'shish tartibni buzmaydi;
  • mijoz default tarmog'iga tayyor bo'lishi kerak — server yangi holat qo'shishi mumkin (versiyalash darsi).

Yozilishi: kanonda kichik harf ("tayyor"). Google AIP — katta harf va pastki chiziq ("IN_PROGRESS"). Yana o'sha qoida: bittasini tanlang.

5. null va "yo'q maydon"

5.1 Ikki xil "yo'q"

JSON'da qiymat yo'qligini ikki xil ifodalash mumkin:

js
const task = {
  id: 7, matn: "Non olish", izoh: undefined, muddat: null,
};
console.log(JSON.stringify(task));
console.log("izoh" in JSON.parse(JSON.stringify(task)));

Konsolda:

text
{"id":7,"matn":"Non olish","muddat":null}
false

undefined li maydon JSON'ga umuman tushmaydi; null esa tushadi. Mijoz uchun bular ikki xil gap:

JSON'da Ma'nosi (kanon qoidasi)
maydon yo'q "bu maydon bu javobda berilmagan" (masalan fields= bilan tanlanmagan)
"keyingi": null "qiymat bor va u — bo'sh" (keyingi sahifa yo'q)

So'rovda ham farq bor — PATCH darsidagi JSON Merge Patch (RFC 7396): maydon yo'q — "o'zgartirma", null — "o'chir". Shuning uchun kanonda {"matn": null} 422 qaytaradi: matn majburiy, uni o'chirib bo'lmaydi.

Qoidani diagramma shaklida kuzating:

flowchart TD
  A[Maydon qiymati yo'q] --> B{Mijoz bu maydonni so'raganmi?}
  B -->|yo'q, fields bilan tanlanmagan| C[maydonni bermang]
  B -->|ha| D{Bo'sh bo'lishi ma'noga egami?}
  D -->|ha: keyingi sahifa yo'q| E[null]
  D -->|ro'yxat| F["bo'sh massiv []"]

5.2 Bo'sh ro'yxat — [], 404 emas

Filtrga mos vazifa topilmasa — 200 va "vazifalar": []. 404 — "bunday manzil yoki resurs yo'q" degani; to'plam esa bor, faqat bo'sh. Massiv maydonlarida null ham bermang: mijoz .map() qilganda null xato beradi, [] esa yo'q.

Tekshirib ko'ring: Mijoz GET /v1/vazifalar?fields=matn so'radi. Javobda bajarildi maydoni bormi? null mi yoki yo'qmi?

Javob

Yo'q — maydon umuman berilmaydi (id va matn dan boshqa). "bajarildi": null yozilsa, mijoz "vazifaning bajarilganlik holati noma'lum" deb tushunishi mumkin. Yo'q maydon esa aniq: "siz buni so'ramadingiz".

6. Yana bir nechta qoida

Qoida Kanon Nega
noma'lum query parametr 400 ?bajarlidi=true (xato yozilgan) jim e'tiborsiz qolsa, mijoz filtrlanmagan ro'yxatni oladi va xatoni sezmaydi
noma'lum tana maydoni 422 (oq ro'yxat) {"rol":"admin"} kabi kutilmagan maydonlar (mass assignment)
mantiqiy maydon nomi sifat yoki holat: bajarildi isBajarildi — ikki tilni aralashtirish
vaqt maydonlari yaratildi, yangilandi har resursda bir xil nom
javob konverti ro'yxat — { vazifalar, sahifa }; bitta resurs — o'zi ro'yxatga keyin maydon qo'shish mumkin bo'lsin (yalang'och massiv kengaymaydi)

Oxirgi qatorga e'tibor bering: GET /v1/vazifalar yalang'och massiv [...] qaytarganda, keyin sahifa yoki versiya qo'shib bo'lmasdi — bu buzuvchi o'zgarish bo'lardi. Obyekt konverti kelajakni ochiq qoldiradi.

7. API qadami: API.md (holat 27)

7.1 Hujjat

Loyiha ildizida yangi fayl — API.md. To'rt bo'lim: konvensiyalar, endpointlar, xatolar katalogi, changelog. Konvensiyalar qismi (kanondan, qisqartirilgan):

Masala Qaror Nega
Maydon nomlari camelCase, o'zbekcha (bajarildi) frontend shu nomlarni ishlatadi
Resurs nomlari ko'plik, kichik harf, kebab-case Google AIP / Zalando bilan bir xil
ID musbat butun son frontend z.int(); 2⁵³ dan oshsa — satr (v2)
Sana-vaqt ISO 8601, UTC, Z mintaqa — faqat ko'rsatishda
Yo'q qiymat maydon berilmaydi; null — faqat ma'nosi bo'lsa farq aniq
Enum kichik harfli satr o'qiladi, kengaytirish buzmaydi
Pul (yo'q) — butun son tiyinda + valyuta float xatosi
Bo'sh ro'yxat [] (200) 404 emas
Noma'lum parametr 400 jim e'tiborsiz qolmasin

Hujjat boshida bitta qator: "Asosiy manzil: /v1. Hamma tana — JSON (application/json; charset=utf-8), xatolar — application/problem+json."

Endpointlar bo'limi (kanondagi API.md dan):

Metod Yo'l Javob
GET /v1/vazifalar 200 { versiya, vazifalar, sahifa } + Link: <…>; rel="next"
POST /v1/vazifalar 201 + Location, ETag; Idempotency-Key qo'llanadi
PUT /v1/vazifalar 200 { versiya, vazifalar } — butun ro'yxat almashtiriladi (atomik)
POST /v1/vazifalar/toplam 201 yoki 207 { natijalar: [{ indeks, holat, vazifa?, xato? }] } (1..100 element)
GET /v1/vazifalar/:id 200 + ETag: "<versiya>", Last-Modified; If-None-Match → 304
PUT /v1/vazifalar/:id 200 — matn va bajarildi majburiy; If-Match → 412
PATCH /v1/vazifalar/:id 200 — application/json yoki application/merge-patch+json; If-Match → 412
DELETE /v1/vazifalar/:id 204; If-Match → 412
GET /v1/teglar 200 { teglar: [{ teg, soni }] }
POST /v1/eksportlar 202 + Location: /v1/eksportlar/:id + Retry-After
GET /v1/eksportlar/:id 200 { id, holat, tayyor, jami, fayl? } (+ Retry-After tayyor bo'lguncha)
GET /v1/eksportlar/:id/fayl 200 text/csv (1 soat saqlanadi)

Jadval ostida: "Ro'yxat parametrlari: bajarildi, teg (takrorlanadi — hammasi), q, sort=-yaratildi,matn, fields=matn,teglar, limit (1..100, sukut 20), offset yoki cursor (birga emas), jami=true."

Xatolar katalogi (type: https://vazifalar-api.example/xatolar/<kod>):

kod status qachon
validatsiya 422 tana qoidaga mos emas; xatolar: [{ joy, xabar }]
parametr 400 query yoki yo'l parametri noto'g'ri
vazifa-topilmadi 404
royxat-toldi 409 1000 ta vazifa
versiya-mos-emas 412 If-Match eskirgan; javobda joriy ETag
idempotentlik-kalit 400 Idempotency-Key yaroqsiz
idempotentlik-boshqa-tana 422 kalit boshqa tana bilan qayta ishlatildi
idempotentlik-jarayonda 409 shu kalitli so'rov hali bajarilmoqda (Retry-After)
eksport-topilmadi / eksport-tayyor-emas 404 / 409
(about:blank) 400/404/405/413/415/500 umumiy HTTP xatolari, title — status matni

Katalog ostida: "Har xato javobida sorovId (= X-Request-Id sarlavhasi) — murojaatda shuni ayting." Bu — foydalanuvchi va qo'llab-quvvatlash xizmati uchun.

Oxirgi bo'lim — changelog, versiyalash darsidagi v1 yozuvi (/v1 prefiksi, Problem Details, { versiya, vazifalar, sahifa }, eksport, toplam; eski yo'llar eskirgan, 2027-01-24 da o'chiriladi).

7.2 Nega Markdown, OpenAPI emas

Hozircha qo'lda yozilgan Markdown — o'qilishi oson, git'da farqi ko'rinadi. Uning kamchiligi: kod bilan avtomatik bog'lanmagan, eskirib qolishi mumkin. Mashina o'qiydigan shartnoma — OpenAPI — keyinroq: Zod sxemalaridan JSON Schema chiqarish (Zod 4 serverda) birinchi qadam, to'liq OpenAPI — OpenAPI darsida.

7.3 public/index.html

Loyihadagi statik sahifadagi havolalar /v1/... ga yangilandi — eskirgan yo'llarga yo'naltirmasin.

7.4 Tekshiruv va commit

Testlar 28 → 31 (+3, test/toplam.test.ts: PUT to'plam, toplam 207/201/422, eksport 202 → polling → CSV, 404). Kanon tekshiruvi (tekshiruv-27): tip 0, lint 0, test 31/31. Yuk (autocannon, band mashina, bitta o'lchov): GET /v1/vazifalar/5 — 6 600 req/s, holat 26 dagi 6 221 bilan bir xil darajada — yangi endpointlar asosiy yo'lni sekinlashtirmadi.

bash
npm run check
git add -A
git commit -m "Bulk: PUT /v1/vazifalar (butun ro'yxat), \
POST /v1/vazifalar/toplam (207); eksport 202 + polling; API.md"

8. Ko'p uchraydigan xatolar

1. Bitta API'da ikki uslub. createdAt va updated_at yonma-yon. Lint yoki sxema tekshiruvi bilan ushlang.

2. Mahalliy sana formati. "24.10.2026", "10/24/2026" — kim qanday o'qishi noma'lum.

3. Vaqt mintaqasisiz sana-vaqt. "2026-10-24T10:00:00" — Z yoki +05:00 yo'q. JS uni mahalliy vaqt deb o'qiydi, server esa UTC deb yozgan bo'lishi mumkin.

4. Pul float da. 19.99 * 3 → 59.97000000000001. Butun son va tiyin.

5. Katta ID son sifatida. 2⁵³ dan keyin jim buziladi.

6. Holat — son kod. "holat": 3 — hujjatsiz tushunib bo'lmaydi.

7. Qoidalar faqat bir kishining boshida. Yozilmagan konvensiya — konvensiya emas. API.md yoki qo'llanmaga havola.

9. Mashqlar

Yechimlar kurs/mashqlar/25/28-konvensiyalar/ da.

1-mashq (oson): to'g'ri variant

  • Sana-vaqt: "24.10.2026 10:00" yoki "2026-10-24T05:00:00Z"?
  • Pul: "narx": 35000.50 yoki "narx": { "summa": 3500050, "valyuta": "UZS" }? Tanlang:
  • Bo'sh natija: 404 yoki 200 + []?
  • Holat: "holat": 2 yoki "holat": "tayyor"?
  • Resurs yo'li: /v1/getVazifa yoki /v1/vazifalar?
Yechim
  • ISO 8601 UTC — tartiblanadi, mintaqa aniq.
  • summa (tiyinda, butun son) + valyuta kodi.
  • 200 va bo'sh massiv — to'plam bor, faqat bo'sh.
  • "tayyor" — o'qiladigan satr enum.
  • /v1/vazifalar — ot, ko'plik; fe'l metodda.

2-mashq (o'rta): rekursiv kalit aylantirish

deepKeys(convert, value) yozing: obyekt va massivlar ichidagi hamma darajadagi kalitlarni aylantirsin, qiymatlarga (satrlar ichiga) tegmasin. toCamel bilan sinang. Bu toza JS — «Ishga tushir» bilan ishlaydi.

Yechim
js
const toCamel = (s) =>
  s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());

function deepKeys(convert, value) {
  if (Array.isArray(value)) {
    return value.map((v) => deepKeys(convert, v));
  }
  if (value !== null && typeof value === "object") {
    return Object.fromEntries(
      Object.entries(value).map(
        ([k, v]) => [convert(k), deepKeys(convert, v)],
      ),
    );
  }
  return value;
}

const row = {
  loyiha_id: 3,
  vazifalar: [
    { vazifa_id: 7, izoh_matni: "qiymat_ichida_tegilmaydi" },
  ],
  egasi: { to_liq_ism: "Malika", oxirgi_kirish: null },
};
console.log(JSON.stringify(deepKeys(toCamel, row)));

Konsolda:

text
{"loyihaId":3,"vazifalar":[{"vazifaId":7,"izohMatni":"qiymat_ichida_tegilmaydi"}],"egasi":{"toLiqIsm":"Malika","oxirgiKirish":null}}

null — typeof null === "object", shuning uchun alohida tekshiruv shart, aks holda Object.entries(null) xato beradi.

3-mashq (qiyin): konvensiya tekshiruvchisi

lintResponse(obj) yozing — javob obyektini konvensiyalarga tekshirib, muammolar ro'yxatini qaytarsin: (1) snake_case kalit, (2) sana-vaqtga o'xshash satr (T bor) Z bilan tugamasa, (3) id maydoni Number.MAX_SAFE_INTEGER dan katta son bo'lsa, (4) summa kasr son bo'lsa. Ichma-ich obyektlarni ham tekshirsin va muammo yo'lini (egasi.oxirgi_kirish) ko'rsatsin.

Yechim
js
function lintResponse(value, path = "", problems = []) {
  if (Array.isArray(value)) {
    value.forEach((v, i) => {
      lintResponse(v, `${path}[${i}]`, problems);
    });
    return problems;
  }
  if (value === null || typeof value !== "object") return problems;
  for (const [key, v] of Object.entries(value)) {
    const at = path ? `${path}.${key}` : key;
    if (key.includes("_")) problems.push(`${at}: snake_case`);
    const isDateTime = typeof v === "string"
      && /^\d{4}-\d\d-\d\dT/.test(v);
    if (isDateTime && !v.endsWith("Z")) {
      problems.push(`${at}: UTC (Z) yo'q`);
    }
    const MAX = Number.MAX_SAFE_INTEGER;
    const tooBig = typeof v === "number" && v > MAX;
    if (key === "id" && tooBig) {
      problems.push(`${at}: 2^53 dan katta son`);
    }
    if (key === "summa" && !Number.isInteger(v)) {
      problems.push(`${at}: pul butun son emas`);
    }
    lintResponse(v, at, problems);
  }
  return problems;
}

const response = {
  id: 9007199254740993,
  yaratildi: "2026-10-24T10:00:00",
  narx: { summa: 35000.5, valyuta: "UZS" },
  egasi: { oxirgi_kirish: "2026-10-24T05:00:00Z" },
  teglar: [{ teg_nomi: "uy" }],
};
for (const p of lintResponse(response)) console.log(p);

Konsolda:

text
id: 2^53 dan katta son
yaratildi: UTC (Z) yo'q
narx.summa: pul butun son emas
egasi.oxirgi_kirish: snake_case
teglar[0].teg_nomi: snake_case

9007199254740993 literal kodda ham …992 bo'ladi, lekin baribir MAX_SAFE_INTEGER dan katta — tekshiruv ishlaydi. Real loyihalarda bunday tekshiruvlarni Spectral kabi vositalar OpenAPI hujjati ustida bajaradi.

4-mashq: API qadami

O'z vazifalar-api ingizda API.md yozing: «API qadami» bo'limidagi konvensiyalar jadvali, endpointlar jadvali (kamida 12 qator), xatolar katalogi va changelog. Har qarorning yonida "nega" ustuni bo'lsin. public/index.html dagi havolalarni /v1 ga o'tkazing. Oldingi darsdagi uchta test bilan birga npm run check toza bo'lgach — holat 27 commit'i.

10. Real ishda

  • Katta jamoalarda API review jarayoni bor: yangi endpoint birlashtirishdan oldin qo'llanma bo'yicha tekshiriladi (Google'da — AIP'lar asosida).
  • Spectral (Stoplight) — OpenAPI hujjatini qoidalar to'plami bilan tekshiruvchi linter; Zalando qoidalari uchun tayyor to'plamlar bor.
  • Yangi dasturchi uchun API.md — birinchi o'qiladigan hujjat: u kod o'qishdan ko'ra tezroq "bu API qanday fikrlaydi"ni ko'rsatadi.
  • Intervyuda dizayn savollari ("pulni qanday saqlaysiz?", "sana formati?", "null yoki yo'q maydon?") — tajribali va yangi dasturchini ajratadi.

Xulosa

  • Konvensiyalarni o'ylab topmang — Google AIP, Microsoft yoki Zalando'dan birini asos qiling va izchil bo'ling.
  • Bitta nomlash uslubi; resurslar ko'plik, kebab-case; fe'l — metodda.
  • Sana — ISO 8601 UTC Z; pul — butun son tiyinda + valyuta; katta ID — satr; enum — satr.
  • Yo'q maydon ≠ null; bo'sh ro'yxat — []; ro'yxat javobi — obyekt konverti.
  • Qarorlar API.md da "nega" bilan yoziladi; noma'lum parametr — 400.

Keyingi dars: Validatsiya: nima uchun, qayerda va qanday — tashqaridan kelgan har qiymatni chegarada tekshiruvchi qayta ishlatiladigan middleware yozamiz.

Manbalar

  • Google API Improvement Proposals — google.aip.dev (AIP 122, 126, 140, 158, 193)
  • Microsoft REST API Guidelines — github.com/microsoft/api-guidelines
  • Zalando RESTful API and Event Guidelines — opensource.zalando.com/restful-api-guidelines
  • RFC 3339 "Date and Time on the Internet: Timestamps" (2002-07) — rfc-editor.org/rfc/rfc3339
  • X Developer — "X IDs" (id_str, JavaScript va 53 bit) — docs.x.com/fundamentals/x-ids
  • Stripe — "Supported currencies: Specify amounts in API requests" (minor unit) — docs.stripe.com/currencies
  • Payme Business — Merchant API, CreateTransaction (amount tiyinda) — developer.help.paycom.uz/metody-merchant-api/createtransaction
  • ISO 4217 valyuta kodlari — iso.org/iso-4217-currency-codes.html
  • RFC 7396 "JSON Merge Patch" (2014-10) — rfc-editor.org/rfc/rfc7396
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
API dizayn konvensiyalari: nomlash, ISO 8601 sana, ID, null, enum va pul — Google AIP va Zalando — IlmHamroh