JSON-API-Designmuster: Bessere REST-APIs entwickeln
Eine gut gestaltete API ist eine Freude in der Nutzung. Eine schlecht gestaltete erzeugt Bugs, Frustration und technische Schulden. Dieser Leitfaden behandelt praxiserprobte Muster fĂŒr die Gestaltung von JSON-REST-APIs, die konsistent, auffindbar und wartbar sind.
Ressourcenbenennung
Ressourcen sind Substantive, keine Verben. Verwenden Sie Pluralnomen fĂŒr Sammlungen und einzelne Ressourcen ĂŒber IDs:
GET /api/users # List users
POST /api/users # Create a user
GET /api/users/123 # Get user 123
PUT /api/users/123 # Update user 123
DELETE /api/users/123 # Delete user 123
Namenskonventionen:
- Kleinbuchstaben mit Bindestrichen verwenden:
/api/blog-posts(nichtblogPostsoderblog_posts) - Verwandte Ressourcen verschachteln:
/api/users/123/orders - Verschachtelung auf 2 Ebenen begrenzen:
/api/users/123/orders/456(nicht tiefer) - Verben in URLs vermeiden:
/api/users/123/activateist akzeptabel fĂŒr Aktionen, die nicht auf CRUD abbildbar sind
Antwort-Envelope
Antworten in einem konsistenten Envelope verpacken:
{
"data": {
"id": "123",
"type": "user",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
},
"meta": {
"requestId": "req_abc123"
}
}
FĂŒr Sammlungen:
{
"data": [
{ "id": "123", "name": "Alice" },
{ "id": "456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20
}
}
Validieren Sie Ihre API-Antworten mit unserem JSON Validator, um sicherzustellen, dass sie Ihrem Schema entsprechen.
Paginierung
Drei gÀngige AnsÀtze:
Offset-basiert (Am einfachsten)
GET /api/users?page=2&per_page=20
{
"data": [...],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
}
}
Vorteil: Einfach, unterstĂŒtzt das Springen zu beliebigen Seiten. Nachteil: Inkonsistente Ergebnisse bei gleichzeitigen EinfĂŒgungen/Löschungen.
Cursor-basiert (Am zuverlÀssigsten)
GET /api/users?cursor=eyJpZCI6MTIzfQ&limit=20
{
"data": [...],
"meta": {
"hasNext": true,
"nextCursor": "eyJpZCI6MTQzfQ"
}
}
Vorteil: Konsistent bei gleichzeitigen Ănderungen, performant bei groĂen DatensĂ€tzen. Nachteil: Kein Springen zu beliebigen Seiten möglich.
Keyset-basiert (Am performantesten)
GET /api/users?after_id=123&limit=20
Verwendet die ID des letzten Elements (oder ein anderes sortiertes Feld), um die nĂ€chste Seite abzurufen. Ăhnlich wie Cursor-basiert, aber mit transparenten Parametern.
Empfehlung: Verwenden Sie Cursor-basierte Paginierung fĂŒr Echtzeit-Feeds und groĂe DatensĂ€tze. Verwenden Sie Offset-basierte Paginierung fĂŒr Admin-Dashboards, bei denen das Seitenspringen wichtig ist.
Filterung und Sortierung
Filterung
GET /api/users?status=active&role=admin
GET /api/users?created_after=2024-01-01
GET /api/users?search=alice
FĂŒr komplexe Filter einen dedizierten Query-Parameter verwenden:
GET /api/users?filter[status]=active&filter[role]=admin
Sortierung
GET /api/users?sort=name # Aufsteigend
GET /api/users?sort=-created_at # Absteigend (PrÀfix mit -)
GET /api/users?sort=-created_at,name # Mehrere Felder
Fehlerbehandlung
Konsistente Fehlerantworten sind entscheidend fĂŒr die API-Benutzerfreundlichkeit:
{
"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"
}
}
Zu verwendende HTTP-Statuscodes:
| Code | Bedeutung | Wann |
|---|---|---|
| 200 | OK | Erfolgreiche GET, PUT |
| 201 | Created | Erfolgreiche POST |
| 204 | No Content | Erfolgreiche DELETE |
| 400 | Bad Request | Validierungsfehler |
| 401 | Unauthorized | Fehlende/ungĂŒltige Authentifizierung |
| 403 | Forbidden | GĂŒltige Authentifizierung, unzureichende Berechtigungen |
| 404 | Not Found | Ressource existiert nicht |
| 409 | Conflict | Doppelte Ressource, Versionskonflikt |
| 422 | Unprocessable | Semantisch ungĂŒltig |
| 429 | Too Many Requests | Rate-Limit ĂŒberschritten |
| 500 | Internal Error | Unerwarteter Serverfehler |
Versionierung
Drei AnsÀtze:
URL-Pfad (Empfohlen)
GET /api/v1/users
GET /api/v2/users
Vorteil: Explizit, einfach zu routen, einfach zu testen.
Header-basiert
GET /api/users
Accept: application/vnd.myapi.v2+json
Vorteil: Saubere URLs. Nachteil: Schwieriger zu testen, weniger auffindbar.
Query-Parameter
GET /api/users?version=2
Vorteil: Einfach zu testen. Nachteil: Optionale Parameter-Semantik.
Empfehlung: URL-Pfad-Versionierung ist die praktischste Wahl. Sie ist explizit, cachebar und funktioniert mit jedem HTTP-Tool.
Datums- und Zeitbehandlung
Immer ISO 8601 in UTC verwenden:
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33Z",
"expiresAt": "2024-12-31T23:59:59Z"
}
Verwenden Sie niemals Unix-Timestamps in API-Antworten â sie sind mehrdeutig (Sekunden vs. Millisekunden) und nicht menschenlesbar. Weitere Informationen zur Timestamp-Behandlung finden Sie in unserem Unix-Timestamps-Leitfaden.
Ratenbegrenzung
Ratenbegrenzungen in Antwort-Headern kommunizieren:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 67
X-RateLimit-Reset: 1705312800
Retry-After: 30
Geben Sie 429 Too Many Requests zurĂŒck, wenn das Limit ĂŒberschritten wird, mit einer klaren Fehlermeldung und einem Retry-After-Header.
HATEOAS (Optional aber wirkungsvoll)
Links zu verwandten Ressourcen und Aktionen einfĂŒgen:
{
"data": {
"id": "123",
"name": "Alice",
"links": {
"self": "/api/users/123",
"orders": "/api/users/123/orders",
"avatar": "/api/users/123/avatar"
}
}
}
Dies macht Ihre API selbstdokumentierend und reduziert die clientseitige URL-Konstruktion.
FAQ
Sollte ich die JSON:API-Spezifikation verwenden oder ein eigenes Format entwerfen?
Die JSON:API-Spezifikation (jsonapi.org) bietet einen umfassenden Standard, kann aber fĂŒr einfache APIs zu ausfĂŒhrlich sein. FĂŒr die meisten Projekte ist es praktischer, ein einfacheres benutzerdefiniertes Format nach den Mustern in diesem Leitfaden zu entwerfen. Verwenden Sie JSON:API, wenn Sie automatische Client-Bibliotheken und einen strikten Standard benötigen.
Wie sollte ich partielle Updates handhaben (PATCH vs PUT)?
Verwenden Sie PUT fĂŒr den vollstĂ€ndigen Ressourcenaustausch (Client sendet alle Felder). Verwenden Sie PATCH fĂŒr partielle Updates (Client sendet nur geĂ€nderte Felder). PATCH mit JSON Merge Patch (RFC 7396) ist der einfachste Ansatz: Senden Sie ein JSON-Objekt mit nur den zu aktualisierenden Feldern und null zum Entfernen eines Feldes.
Verwandte Ressourcen
- JSON Formatter â API-Antworten fĂŒr bessere Lesbarkeit formatieren
- JSON-Schema-Validierungsleitfaden â API-Payloads mit JSON Schema validieren
- JWT Tokens erklĂ€rt â Ihre APIs mit JSON Web Tokens absichern