Mundarija (31)
- Bu darsda
- 1. Nega bu kerak?
- 2. Mavjud qo'llanmalar
- 2.1 Uchta asosiy manba
- 2.2 Bu kursda nimani allaqachon qildik
- 3. Nomlash
- 3.1 JSON maydonlari: camelCase yoki snake_case
- 3.2 URL va query
- 4. Qiymat formatlari
- 4.1 Sana va vaqt — ISO 8601, UTC
- 4.2 ID — son yoki satr
- 4.3 Pul — butun son, eng kichik birlikda
- 4.4 Enum — satr
- 5. null va "yo'q maydon"
- 5.1 Ikki xil "yo'q"
- 5.2 Bo'sh ro'yxat — [], 404 emas
- 6. Yana bir nechta qoida
- 7. API qadami: API.md (holat 27)
- 7.1 Hujjat
- 7.2 Nega Markdown, OpenAPI emas
- 7.3 public/index.html
- 7.4 Tekshiruv va commit
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): to'g'ri variant
- 2-mashq (o'rta): rekursiv kalit aylantirish
- 3-mashq (qiyin): konvensiya tekshiruvchisi
- 4-mashq: API qadami
- 10. Real ishda
- Xulosa
- Manbalar
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 (
camelCaseyokisnake_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" vanullfarqi 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 qarorlariniAPI.mdda yozadi.
Bu darsda
- Katta kompaniyalarning API qo'llanmalari nima uchun kerakligini va qayerdan topishni bilasiz.
- Nomlash, sana, ID, pul, enum,
nullbo'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-apiuchunAPI.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 | 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:
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:
{ 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 (
/getVazifalaremas) — 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), Pythondatetime.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:
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:
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
identityustuni (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:
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:
0.30000000000000004
11000000 110000Kasr 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:
{ "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:
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:
35 000 so'm
12 500,50 so'm
0,05 so'mvazifalar-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
2nimaligini hech kim eslamaydi; - yangi qiymat qo'shish tartibni buzmaydi;
- mijoz
defaulttarmog'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:
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:
{"id":7,"matn":"Non olish","muddat":null}
falseundefined 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=matnso'radi. Javobdabajarildimaydoni bormi?nullmi 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.
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.50yoki"narx": { "summa": 3500050, "valyuta": "UZS" }? Tanlang: - Bo'sh natija: 404 yoki
200+[]? - Holat:
"holat": 2yoki"holat": "tayyor"? - Resurs yo'li:
/v1/getVazifayoki/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
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:
{"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
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:
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_case9007199254740993 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?", "
nullyoki 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.mdda "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(amounttiyinda) — 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
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!