JSON API Best Practices for Developers

Design better JSON APIs with consistent naming, structured responses, proper pagination, error handling, and performance optimizations used by top engineering teams.

JSONTech-TeamFebruary 1, 202510 min read

Warum API-Design wichtig ist

Ein gut gestaltetes JSON-API ist der Unterschied zwischen einer Integration, die einen Nachmittag dauert, und einer, die eine Woche in Anspruch nimmt. Gutes API-Design reduziert Support-Tickets, macht Ihre Dokumentation kürzer und ermöglicht es den Nutzern, vorherzusagen, wie Dinge funktionieren, bevor sie die Dokumentation lesen.

Die Muster in diesem Leitfaden sind nicht theoretisch — sie stammen von APIs bei Stripe, GitHub, Slack und anderen Unternehmen, die für hervorragende Entwicklererfahrungen bekannt sind. Lassen Sie uns jedes einzelne durchgehen.

Namenskonventionen

Die beiden dominierenden Stile für JSON-Eigenschaftsnamen sind camelCase und snake_case. Beides ist in Ordnung, solange Sie sich für eines entscheiden und es überall verwenden.

KonventionBeispielVerwendet vonÖkosystem
camelCasefirstName, createdAtGoogle APIs, AzureJavaScript / TypeScript-Frontends
snake_casefirst_name, created_atStripe, GitHub, SlackPython / Ruby-Backends

Richtlinie: Wählen Sie die Konvention, die zu Ihrem primären Verbraucher-Ökosystem passt. Wenn Ihr API hauptsächlich von JavaScript-Frontends genutzt wird, vermeidet camelCase Reibungen. Wenn Ihr Backend Python oder Ruby ist und das API B2B ist, ist snake_case idiomatisch.

Was auch immer Sie wählen, seien Sie absolut konsistent. Das Mischen von user_name und firstName in derselben Antwort untergräbt das Vertrauen schneller als fast alles andere.

Konsistente Antwortstruktur

Jede Antwort von Ihrem API sollte einem vorhersehbaren Rahmen folgen. Hier ist ein Muster, das für die meisten APIs funktioniert:

Erfolgsantwort

{
  "data": {
    "id": "usr_abc123",
    "email": "alice@example.com",
    "name": "Alice Johnson",
    "created_at": "2025-01-15T09:30:00Z"
  },
  "meta": {
    "request_id": "req_7f2a9c"
  }
}

Listenantwort

{
  "data": [
    { "id": "usr_abc123", "name": "Alice Johnson" },
    { "id": "usr_def456", "name": "Bob Smith" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "per_page": 20,
    "request_id": "req_8b3d1e"
  }
}

Fehlerantwort

{
  "error": {
    "code": "validation_error",
    "message": "Der Anfrageinhalt enthält ungültige Felder.",
    "details": [
      {
        "field": "email",
        "message": "Muss eine gültige E-Mail-Adresse sein."
      },
      {
        "field": "age",
        "message": "Muss mindestens 13 Jahre alt sein."
      }
    ]
  },
  "meta": {
    "request_id": "req_4c8e2a"
  }
}

Das Schlüsselprinzip: data ist bei Erfolg vorhanden, error ist bei Misserfolg vorhanden, und meta erscheint in beiden für die Anforderungsverfolgung und Paginierung. Verbraucher können einen einzigen Antwort-Handler schreiben, der zuerst nach error sucht.

Versuchen Sie es selbst: Fügen Sie eine API-Antwort in unseren JSON Formatter ein, um die Struktur zu inspizieren und Inkonsistenzen zu erkennen.

Paginierungsmuster

Die meisten Listenendpunkte benötigen eine Paginierung. Es gibt drei gängige Ansätze, jeder mit unterschiedlichen Vor- und Nachteilen:

1. Offset-Paginierung

Der einfachste Ansatz. Der Client gibt eine Seitenzahl oder einen Offset an:

GET /api/users?page=3&per_page=20

{
  "data": [...],
  "meta": {
    "total": 142,
    "page": 3,
    "per_page": 20,
    "total_pages": 8
  }
}

2. Cursor-Paginierung

Anstelle von Seitenzahlen gibt der Server einen undurchsichtigen Cursor zurück, der auf die nächste Ergebnismenge zeigt:

GET /api/users?limit=20&after=cursor_abc123

{
  "data": [...],
  "meta": {
    "has_more": true,
    "next_cursor": "cursor_def456"
  }
}

3. Keyset-Paginierung

Verwendet einen echten Spaltenwert (wie einen Zeitstempel oder eine ID) als Cursor. Dies ist Cursor-Paginierung ohne die Undurchsichtigkeit:

GET /api/users?limit=20&created_after=2025-01-15T09:30:00Z

{
  "data": [...],
  "meta": {
    "has_more": true,
    "next_created_after": "2025-01-16T14:22:00Z"
  }
}

Paginierungsvergleich

AspektOffsetCursorKeyset
Springe zu Seite NJaNeinNein
GesamtanzahlEinfach einzufügenTeuerTeuer
Leistung bei großen TabellenVerschlechtert sich (OFFSET scan rows)KonsistentKonsistent
Handhabt Einfügungen/LöschungenKann Elemente überspringen oder duplizierenStabilStabil
ImplementierungskomplexitätNiedrigMittelMittel
Verwendet vonTraditionelle Web-AppsStripe, SlackTwitter / X

Richtlinie: Verwenden Sie die Offset-Paginierung für Admin-Dashboards und interne Tools, bei denen Benutzer zu bestimmten Seiten springen müssen. Verwenden Sie Cursor- oder Keyset-Paginierung für öffentliche APIs, unendliche Scroll-UIs und jede Datensatz, der sich häufig ändert.

Fehlerbehandlung

Gute Fehlerantworten sagen dem Verbraucher was schiefgelaufen ist, wo und idealerweise wie man es behebt. Hier ist die Struktur, die wir empfehlen:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Sie haben das Limit von 100 Anfragen pro Minute überschritten.",
    "details": [],
    "doc_url": "https://docs.example.com/errors/rate-limit"
  }
}

Der code ist eine maschinenlesbare Zeichenfolge (nicht ein HTTP-Statuscode — dieser gehört in die tatsächliche HTTP-Antwort). Die message ist menschenlesbar. Das details-Array bietet feldspezifische Fehler für Validierungsfehler. Und doc_url verlinkt auf die Dokumentation über den Fehler.

Häufige Fehlercodes und deren HTTP-Statuszuordnungen:

HTTP-StatusFehlercodeWann zu verwenden
400validation_errorAnfrageinhalt erfüllt nicht die Schema-Validierung
401unauthorizedFehlende oder ungültige Authentifizierung
403forbiddenAuthentifiziert, hat aber keine Berechtigung
404not_foundRessource existiert nicht
409conflictDuplizierte Ressource oder Statuskonflikt
422unprocessable_entityGültiges JSON, aber semantisch falsch
429rate_limit_exceededZu viele Anfragen
500internal_errorUnerwarteter Serverfehler

Datentypen und Formatierung

Die richtigen Datentypen zu verwenden, verhindert eine ganze Kategorie von Integrationsfehlern:

Daten und Zeiten

Verwenden Sie immer das ISO 8601-Format mit Zeitzoneninformationen:

{
  "created_at": "2025-01-15T09:30:00Z",
  "expires_at": "2025-02-15T23:59:59+05:30"
}

Verwenden Sie niemals Unix-Zeitstempel in Antwortkörpern — sie sind nicht menschenlesbar und schaffen Zeitzonenambiguität. Wenn Sie Unix-Zeitstempel benötigen (z. B. für JWT-Ansprüche), dokumentieren Sie dies klar.

Große Zahlen

Der Number-Typ von JavaScript verliert die Präzision über 2^53 - 1 (9.007.199.254.740.991). Wenn Ihre IDs oder Geldwerte diesen Wert überschreiten, verwenden Sie Strings:

{
  "id": "9223372036854775807",
  "amount": "99.99",
  "currency": "USD"
}

Stripe, Twitter und Discord verwenden aus genau diesem Grund String-IDs.

Null vs. Fehlend

Definieren Sie eine klare Konvention und dokumentieren Sie sie:

  • null — Das Feld existiert, hat aber keinen Wert (z. B. der Benutzer hat noch keine Biografie festgelegt).
  • Fehlender Schlüssel — Das Feld ist für diese Ressource nicht relevant oder wurde nicht angefordert (z. B. in einer partiellen Antwort).

Viele APIs enthalten null-Felder, um eine konsistente Form zu bewahren, was es den Clients erleichtert, typisierte Schnittstellen zu schreiben, ohne überall optionale Verkettungen zu verwenden.

Booleans

Verwenden Sie echte JSON-Boolean-Werte, nicht Strings oder Ganzzahlen:

// Gut
{ "is_active": true }

// Schlecht
{ "is_active": "true" }
{ "is_active": 1 }

Versionierungsstrategien

APIs entwickeln sich weiter. Sie benötigen eine Strategie, um Änderungen vorzunehmen, ohne bestehende Verbraucher zu brechen. Die drei Hauptansätze:

  • URL-Versionierung: /v1/users, /v2/users. Der häufigste und sichtbarste Ansatz. Verwendet von Stripe, GitHub und Twilio. Einfach zu verstehen, einfach zu routen, kann jedoch zu Code-Duplikation führen.
  • Header-Versionierung: Accept: application/vnd.api+json;version=2. Sauberere URLs, aber weniger entdeckbar. Verwendet von GitHub (als Alternative) und Azure.
  • Abfrageparameter: /users?version=2. Einfach, aber verunreinigt die Abfragezeichenfolge. In der Praxis weniger verbreitet.

Richtlinie: URL-Versionierung ist der pragmatische Standard. Es ist explizit, cachebar und funktioniert mit jedem HTTP-Client. Deviieren Sie nur, wenn Sie einen spezifischen technischen Grund haben.

Kompression

JSON ist Text und komprimiert außergewöhnlich gut. Aktivieren Sie immer die Kompression für API-Antworten:

AlgorithmusKompressionsverhältnisGeschwindigkeitBrowserunterstützung
gzipGut (70–80% Reduktion)SchnellUniversell
Brotli (br)Besser (75–85% Reduktion)Etwas langsamer zu komprimierenAlle modernen Browser

Für eine typische JSON-Antwort von 50KB reduziert gzip sie auf etwa 10–15KB, und Brotli auf etwa 8–12KB. Der Server sollte den Accept-Encoding-Header respektieren und entsprechend wählen. Die meisten Reverse-Proxys (Nginx, Cloudflare) erledigen dies automatisch.

Leistungstipps

Partielle Antworten (Feldauswahl)

Lassen Sie Verbraucher nur die Felder anfordern, die sie benötigen. Dies reduziert die Payload-Größe und die Datenbanklast:

GET /api/users?fields=id,name,email

{
  "data": [
    { "id": "usr_abc123", "name": "Alice", "email": "alice@example.com" }
  ]
}

Google APIs nennt dies "partielle Antworten" und unterstützt es über alle Endpunkte hinweg. Es ist besonders wertvoll für mobile Clients mit langsamen Verbindungen.

Sparse Fieldsets

Für APIs, die verwandte Ressourcen zurückgeben, lassen Sie Verbraucher steuern, welche Felder für jeden Ressourcentyp enthalten sind:

GET /api/articles?include=author&fields[article]=title,body&fields[author]=name

Dies ist ein Muster aus der JSON:API-Spezifikation. Es beseitigt das N+1-Abfrageproblem auf der Client-Seite, während die Payloads minimal bleiben.

ETags und bedingte Anfragen

Geben Sie einen ETag-Header mit Antworten zurück. Clients können If-None-Match bei nachfolgenden Anfragen senden, und Sie geben 304 Not Modified (leerer Körper) zurück, wenn sich nichts geändert hat. Dies spart Bandbreite und Verarbeitungszeit für Ressourcen, die sich nicht häufig ändern.

Zusammenfassungs-Checkliste

Bevor Sie Ihr API veröffentlichen, gehen Sie diese Checkliste durch:

  • Konsistente Namenskonvention (camelCase oder snake_case) über alle Endpunkte hinweg.
  • Vorhersehbarer Antwortrahmen mit data, error und meta.
  • Paginierung auf allen Listenendpunkten mit dokumentierten Grenzen.
  • Strukturierte Fehlerantworten mit maschinenlesbaren Codes, Nachrichten und feldspezifischen Details.
  • ISO 8601-Daten, String-IDs für große Zahlen, echte Booleans.
  • Dokumentierte und durchgesetzte API-Versionierungsstrategie.
  • gzip- oder Brotli-Kompression aktiviert.
  • Feldauswahl oder sparse Fieldsets für leistungssensitive Verbraucher.

Versuchen Sie es selbst: Formatieren und validieren Sie Ihre API-Antworten mit unserem JSON Formatter, um sicherzustellen, dass sie einer sauberen, konsistenten Struktur folgen.

Verwandte Tools