alltools.one
API
2025-06-30
9 min
alltools.one Team
JSONAPIRESTDesign PatternsBackend

Pola Desain JSON API: Membangun REST API yang Lebih Baik

API yang dirancang dengan baik menyenangkan untuk digunakan. Yang dirancang buruk menciptakan bug, frustrasi, dan utang teknis. Panduan ini membahas pola-pola teruji untuk merancang JSON REST API yang konsisten, mudah ditemukan, dan mudah dipelihara.

Penamaan Resource

Resource adalah kata benda, bukan kata kerja. Gunakan kata benda jamak untuk koleksi dan resource tunggal melalui ID:

GET    /api/users          # Daftar pengguna
POST   /api/users          # Buat pengguna
GET    /api/users/123      # Ambil pengguna 123
PUT    /api/users/123      # Perbarui pengguna 123
DELETE /api/users/123      # Hapus pengguna 123

Konvensi penamaan:

  • Gunakan huruf kecil dengan tanda hubung: /api/blog-posts (bukan blogPosts atau blog_posts)
  • Sarangkan resource terkait: /api/users/123/orders
  • Batasi penyarangan hingga 2 tingkat: /api/users/123/orders/456 (tidak lebih dalam)
  • Hindari kata kerja di URL: /api/users/123/activate dapat diterima untuk aksi yang tidak dipetakan ke CRUD

Envelope Respons

Bungkus respons dalam envelope yang konsisten:

{
  "data": {
    "id": "123",
    "type": "user",
    "attributes": {
      "name": "Alice",
      "email": "alice@example.com",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

Untuk koleksi:

{
  "data": [
    { "id": "123", "name": "Alice" },
    { "id": "456", "name": "Bob" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "perPage": 20
  }
}

Validasi respons API Anda dengan JSON Validator kami untuk memastikan sesuai dengan skema Anda.

Paginasi

Tiga pendekatan umum:

Berbasis Offset (Paling Sederhana)

GET /api/users?page=2&per_page=20
{
  "data": [...],
  "meta": {
    "page": 2,
    "perPage": 20,
    "total": 142,
    "totalPages": 8
  }
}

Kelebihan: Sederhana, mendukung lompat ke halaman mana pun. Kekurangan: Hasil tidak konsisten dengan insert/delete bersamaan.

Berbasis Cursor (Paling Andal)

GET /api/users?cursor=eyJpZCI6MTIzfQ&limit=20
{
  "data": [...],
  "meta": {
    "hasNext": true,
    "nextCursor": "eyJpZCI6MTQzfQ"
  }
}

Kelebihan: Konsisten dengan perubahan bersamaan, performa baik pada dataset besar. Kekurangan: Tidak dapat melompat ke halaman sembarang.

Berbasis Keyset (Paling Performa)

GET /api/users?after_id=123&limit=20

Menggunakan ID item terakhir (atau field terurut lainnya) untuk mengambil halaman berikutnya. Mirip dengan berbasis cursor tetapi dengan parameter yang transparan.

Rekomendasi: Gunakan berbasis cursor untuk feed real-time dan dataset besar. Gunakan berbasis offset untuk dashboard admin di mana perpindahan halaman penting.

Pemfilteran dan Pengurutan

Pemfilteran

GET /api/users?status=active&role=admin
GET /api/users?created_after=2024-01-01
GET /api/users?search=alice

Untuk filter kompleks, pertimbangkan parameter query khusus:

GET /api/users?filter[status]=active&filter[role]=admin

Pengurutan

GET /api/users?sort=name          # Menaik
GET /api/users?sort=-created_at   # Menurun (awali dengan -)
GET /api/users?sort=-created_at,name  # Beberapa field

Penanganan Error

Respons error yang konsisten sangat penting untuk kegunaan API:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "value": "not-an-email"
      },
      {
        "field": "age",
        "message": "Must be between 0 and 150",
        "value": -5
      }
    ]
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

Kode status HTTP yang digunakan:

KodeArtiKapan
200OKGET, PUT berhasil
201CreatedPOST berhasil
204No ContentDELETE berhasil
400Bad RequestError validasi
401UnauthorizedAuth hilang/tidak valid
403ForbiddenAuth valid, izin tidak cukup
404Not FoundResource tidak ada
409ConflictResource duplikat, konflik versi
422UnprocessableSecara semantik tidak valid
429Too Many RequestsBatas rate terlampaui
500Internal ErrorError server yang tidak terduga

Versioning

Tiga pendekatan:

Path URL (Direkomendasikan)

GET /api/v1/users
GET /api/v2/users

Kelebihan: Eksplisit, mudah dirutekan, mudah diuji.

Berbasis Header

GET /api/users
Accept: application/vnd.myapi.v2+json

Kelebihan: URL bersih. Kekurangan: Lebih sulit diuji, kurang mudah ditemukan.

Parameter Query

GET /api/users?version=2

Kelebihan: Mudah diuji. Kekurangan: Semantik parameter opsional.

Rekomendasi: Versioning path URL adalah pilihan paling praktis. Eksplisit, dapat di-cache, dan berfungsi dengan setiap alat HTTP.

Penanganan Tanggal dan Waktu

Selalu gunakan ISO 8601 dalam UTC:

{
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T14:22:33Z",
  "expiresAt": "2024-12-31T23:59:59Z"
}

Jangan pernah gunakan Unix timestamp dalam respons API — mereka ambigu (detik vs milidetik) dan tidak mudah dibaca manusia. Untuk lebih lanjut tentang penanganan timestamp, lihat panduan Unix Timestamps kami.

Pembatasan Rate

Komunikasikan batas rate di header respons:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 67
X-RateLimit-Reset: 1705312800
Retry-After: 30

Kembalikan 429 Too Many Requests saat batas terlampaui, dengan pesan error yang jelas dan header Retry-After.

HATEOAS (Opsional tetapi Powerful)

Sertakan tautan ke resource dan aksi terkait:

{
  "data": {
    "id": "123",
    "name": "Alice",
    "links": {
      "self": "/api/users/123",
      "orders": "/api/users/123/orders",
      "avatar": "/api/users/123/avatar"
    }
  }
}

Ini membuat API Anda self-documenting dan mengurangi konstruksi URL di sisi klien.

FAQ

Haruskah saya menggunakan spesifikasi JSON:API atau merancang format sendiri?

Spesifikasi JSON:API (jsonapi.org) menyediakan standar yang komprehensif, tetapi bisa verbose untuk API sederhana. Untuk sebagian besar proyek, merancang format kustom yang lebih sederhana mengikuti pola-pola dalam panduan ini lebih praktis. Gunakan JSON:API jika Anda membutuhkan library klien otomatis dan standar yang ketat.

Bagaimana seharusnya saya menangani pembaruan parsial (PATCH vs PUT)?

Gunakan PUT untuk penggantian resource lengkap (klien mengirim semua field). Gunakan PATCH untuk pembaruan parsial (klien mengirim hanya field yang berubah). PATCH dengan JSON Merge Patch (RFC 7396) adalah pendekatan paling sederhana: kirim objek JSON dengan hanya field yang akan diperbarui, dan null untuk menghapus field.

Sumber Terkait

Published on 2025-06-30
JSON API Design Patterns: Building Better REST APIs | alltools.one