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": "[email protected]",
"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
🛠️ Jetzt ausprobieren: JSON Formatter | JSON Schema — 100% kostenlos, alles wird in Ihrem Browser verarbeitet. Keine Daten hochgeladen.