GraphQL-Schemata Schreiben, Formatieren und Verstehen von SDL ohne Boilerplate
GraphQL-Schemata sind selbst dokumentierende Verträge zwischen Server und Client. Dieses Handbuch führt Sie schrittweise durch die Schema-Definition-Sprache (SDL) – Arten, Skalare, Abfragen, Mutationen, Eingabetypen, Enums und Interfaces –, damit Sie Schemata sicher lesen und schreiben können.
Wenn Sie bereits mit REST-APIs gearbeitet haben und dann zum ersten Mal einen GraphQL-Schema öffnen, wird das Syntaxverhalten wahrscheinlich vertraut, aber nicht vollständig parsbar erscheinen. Das ist normal. Die Schema-Definition-Sprache (SDL) ist kompakt, aber jede Zeile trägt viel Bedeutung. Dieser Artikel zerlegt sie auf, damit Sie Schemata lesen und schreiben können, ohne sich fünf Minuten lang an die Dokumentation zu erinnern.
Was ein GraphQL-Schema tatsächlich ist
Ein GraphQL-Schema ist der Vertrag zwischen Ihrem API-Server und jedem Client, der ihn aufruft. Es definiert genau, welche Daten existieren, welche Operationen verfügbar sind und wie die Antworten aussehen. Im Gegensatz zu REST – wo Sie Endpunkte durch Dokumentation, Ausprobieren und Fehlerbehebung entdecken – macht GraphQL den Vertrag explizit und maschinenlesbar.
Jede GraphQL-API beginnt mit einem in SDL geschriebenen Schema. Der Server validiert alle Abfragen gegen dieses Schema im Laufzeitmodus. Wenn ein Client einen Feldwert anfordert, der nicht im Schema existiert, wird die Anfrage vor dem Start eines Resolvers abgelehnt. Dies ist der Kernwert des GraphQL-Typensystems: Das Schema ist die Quelle der Wahrheit für die Oberfläche Ihrer API.
Grundlagen der SDL: Typen, Abfragen und Mutationen
Jede SDL-Datei wird aus Typdefinitionen aufgebaut. Hier ist das kleinste nützliche Schema möglich:
type Query {
hello: String
}
Query ist der Einstiegspunkt für Lesvorgänge. Jedes Schema muss einen haben. Das Feld hello gibt ein String – eine der fünf integrierten skalaren Typen – zurück.
Die fünf integrierten Skalartypen sind:
- String – UTF-8-Text
- Int – 32-Bit-gesigniertes Ganzzahl
- Float – doppelt genaue Gleitkomma-Zahl
- Boolean – wahr oder falsch
- ID – eine eindeutige Identifikation, serialisiert als String
Realistische Schemata definieren benutzerdefinierte Objekttypen. Hier ist ein typischerer Muster:
type User {
id: ID!
name: String!
email: String!
role: UserRole!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String
author: User!
publishedAt: DateTime
}
type Query {
user(id: ID!): User
posts: [Post!]!
}
In diesen 20 Zeilen geschieht viel. Lassen Sie uns es aufschlüsseln.
Nicht-Null-Felder und Listen
Der ! nach einem Typ bedeutet, dass das Feld nicht-Null ist – es wird niemals nullzurückgeben. Ohne diese Angabe ist das Feld nullable und der Client muss einen fehlenden Wert behandeln. Diese Unterscheidung ist im Laufzeitverhalten wichtig: Wenn ein nicht-Null-Feld ein Resolver auslöst oder null zurückgibt, wird null von GraphQL nach oben im Baum propagiert, was möglicherweise auch übergeordnete Felder null macht.
Listen verwenden eckige Klammern: [Post] ist eine nullable Liste von nullable Posts. [Post!]! ist eine nicht-Null-Liste von nicht-Null-Posts. Das ist die Version, die Sie normalerweise wünschen – ein Feld, das immer ein Array (eventuell leer) zurückgibt, und jedes Element in diesem Array ist immer ein echtes Objekt, nicht null.
Die vier Kombinationen, ausgeschrieben:
[Post]– nullable Liste, nullable Elemente (selten nützlich)[Post!]– nullable Liste, nicht-Null-Elemente[Post]!– nicht-Null-Liste, nullable Elemente[Post!]!– nicht-Null-Liste, nicht-Null-Elemente (am häufigsten)
Mutationen: Daten schreiben
Abfragen sind schreibgeschützt. Mutationen behandeln Schreibvorgänge. Der Mutation Typ wird auf die gleiche Weise wie Queryaufgebaut, aber nach Konvention haben seine Felder Nebeneffekte:
type Mutation {
createPost(input: CreatePostInput!): Post!
deletePost(id: ID!): Boolean!
}
Beachten CreatePostInput! – das ist ein Eingabetyp, der direkt zum nächsten Konzept führt.
Eingabetypen im Vergleich zu Ausgabetypen
Dies ist einer der häufigsten Punkte der Verwirrung in GraphQL-Schemata. Sie können keinen Objekttyp wie Post als Argument einer Mutation wiederverwenden. SDL hat zwei separate Arten von Typen, um einen Grund dafür zu haben:
- Objekttypen (
type) – verwendet in Antworten. Kann Resolven und komplexe Feldlogik enthalten. - Eingabetypen (
input) – verwendet in Argumenten. Einfache Daten, keine Resolven. Felder können nur skalare oder andere Eingabetypen referenzieren.
input CreatePostInput {
title: String!
body: String
authorId: ID!
}
Die Trennung sorgt dafür, dass die Argumentvalidierung sauber bleibt und verhindert, dass sich bei der Verwendung von Ausgabetypen (die sich gegenseitig in komplexen Graphen referenzieren können) Kreuzverbindungen ergeben.
Benutzerdefinierte Skalatypen
Die fünf integrierten Skalatypen decken nicht alles ab. Ein Datum-Text, eine URL, ein JSON-Block – diese benötigen benutzerdefinierte Skalatypen. Sie werden wie folgt deklariert:
scalar DateTime
scalar JSON
scalar URL
Die Skalatypen-Deklaration gibt SDL den Namen an. Die tatsächliche Serialisierung, Deserialisierung und Validierung erfolgen in der Serverimplementierung – nicht in der Schema-Datei. Bibliotheken wie graphql-scalars bieten fertige Implementierungen für gängige Typen, sodass Sie sie nicht von Grund auf schreiben müssen.
Verwenden Sie benutzerdefinierte Skalatypen, wenn ein String technisch korrekt ist, aber semantisch falsch ist. Ein Feld, das als DateTime typisiert ist, kommuniziert die Absicht; ein Feld, das als String typisiert ist, zwingt den Client, die Formatierung zu erraten.
Enums
Enums beschränken ein Feld auf eine feste Menge an Zeichenketten. Sie sind zuverlässiger als rohe Zeichenketten, weil das Schema die erlaubten Werte auf Typenebene verlangt:
enum UserRole {
ADMIN
EDITOR
VIEWER
}
enum PostStatus {
DRAFT
PUBLISHED
ARCHIVED
}
Ein Feld, das als UserRole typisiert ist, gibt niemals einen unerwarteten String zurück. Ein Feld, das als String typisiert ist, kann alles zurückgeben. Verwenden Sie Enums, wenn die Menge an Werten bekannt, stabil und für Clients sinnvoll ist – es macht die Schema-Introspektion erheblich nützlicher.
Interfaces und Unions
Wenn ein Feld unterschiedliche Arten von Objekten zurückgeben kann, bietet GraphQL zwei Mechanismen: Interfaces und Unions.
Interfaces definieren eine gemeinsame Menge an Feldern. Typen, die das Interface implementieren, müssen diese Felder enthalten:
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
}
type Post implements Node {
id: ID!
title: String!
}
Unions gruppieren Typen ohne die Notwendigkeit gemeinsamer Felder. Sie sind nützlich, wenn die möglichen Typen strukturell nichts gemeinsam haben:
union SearchResult = User | Post | Comment
type Query {
search(query: String!): [SearchResult!]!
}
Kunden verwenden Inline-Fragmente, um jedes Typ in einer Union oder einem Interface zu behandeln: ... on User { name }. Wenn Sie polymorphe Daten zurückgeben, bevorzugen Sie Interfaces, wenn Typen gemeinsame Felder haben, und Unions, wenn sie keine haben.
Direktiven
Direktiven ändern das Verhalten auf Feld- oder Typebene. Zwei sind in jeder GraphQL-Implementierung enthalten:
@deprecated(reason: "Use newField instead")– markiert ein Feld als veraltet in der Introspektion@skip(if: Boolean)und@include(if: Boolean)– clientseitige Bedingungen in Abfragen
Sie können auch benutzerdefinierte Direktiven für Dinge wie Authentifizierungsschutz, Rate-Limit-Hinweise oder Caching-Annotationen definieren. Sie werden in der Schema deklariert und auf dem Server implementiert:
directive @auth(requires: UserRole = ADMIN) on FIELD_DEFINITION
type Mutation {
deleteUser(id: ID!): Boolean! @auth(requires: ADMIN)
}
GraphQL im Vergleich zu REST: Wann ist welches die richtige Wahl?
Das schemaerste-Approach von GraphQL lohnt sich in bestimmten Situationen. Es ist die richtige Wahl, wenn:
- Mehrere Clients (Web, Mobil, Drittanbieter) unterschiedliche Teile derselben Daten benötigen
- Sie die API ohne Versionierung evolviert – Felder können frei hinzugefügt werden, veraltet werden, nicht entfernt
- Das Domänenmodell ist natürlich graphförmig mit komplexen Beziehungen zwischen Entitäten
- Sie ein selbst dokumentierendes API wollen, das Clients über Introspektion erkunden können
REST ist immer noch die bessere Wahl, wenn:
- Sie einfache CRUD-Endpunkte mit vorhersehbaren, flachen Payloads erstellen
- HTTP-Caching entscheidend ist – GraphQL-POST-Anfragen werden standardmäßig nicht gecached
- Das Team ist klein und die API-Oberfläche stabil – der Aufwand von REST ist geringer
- Sie das N+1-Problem haben und keine DataLoader-Konfiguration vornehmen wollen
Das N+1-Problem ist wertvoll zu pausieren. In einem GraphQL-Resolver, der posts und jedes Post-Objekt authorliefert, führt eine naive Implementierung eine Datenbankabfrage pro Post, um den Autor zu laden. Mit 50 Posts sind das 51 Abfragen für eine einzige Anfrage. REST hat dieses Problem nicht, weil Sie genau steuern, was pro Endpunkt ausgeführt wird. In GraphQL wird es mit Batch-Verarbeitung (DataLoader oder Äquivalent) behoben – es ist lösbar, aber es ist ein weiteres Element, das korrekt konfiguriert werden muss.
Formatieren und Validieren Sie Ihr SDL
Schema-Dateien sammeln mit wachsenden Teams unkonstante Einrückung, ungleiche Abstände und strukturelle Drift. Bevor Sie Schema-Änderungen commiten, führen Sie sie durch einen Formatter, um die Einrückung zu normalisieren, Felder zu sortieren und Syntaxfehler vor dem CI zu erkennen.
Der GraphQL Schema Formatierer on iotools.cloud macht genau das – fügen Sie Ihr SDL ein, erhalten Sie saubere, konsistente Ausgabe mit Inline-Validierungsfehlern. Es behandelt mehrfache Typen, benutzerdefinierte Skalatypen, Direktiven und die Fälle, die bei manueller Formatierung auftreten. Nützlich als letzter Schritt vor Commit oder beim Teilen eines Schemas mit einem anderen Team.
Das könnte Ihnen auch gefallen
Erweiterungen installieren
IO-Tools zu Ihrem Lieblingsbrowser hinzufügen für sofortigen Zugriff und schnellere Suche
恵 Die Anzeigetafel ist eingetroffen!
Anzeigetafel ist eine unterhaltsame Möglichkeit, Ihre Spiele zu verfolgen. Alle Daten werden in Ihrem Browser gespeichert. Weitere Funktionen folgen in Kürze!
Unverzichtbare Tools
Alle Neuheiten
AlleAktualisieren: Unser neuestes Werkzeug was added on Juni 26, 2026
