Les pubs vous déplaisent ? Aller Sans pub Auj.

Schémas GraphQL Écrire, Formater et Comprendre SDL sans code répétitif

Mis à jour le

Les schémas GraphQL sont des contrats auto-documentés entre serveur et client. Ce guide vous guide pas à pas dans la langue de définition de schéma (SDL) — types, scalaires, requêtes, mutations, types d'entrée, enums et interfaces — afin que vous puissiez lire et écrire des schémas avec confiance.

Schémas GraphQL : Écrivez, formatez et comprenez l'SDL sans boilerplate 1
ANNONCE · Supprimer ?

Si vous avez travaillé avec des API REST et que vous ouvrez pour la première fois un schéma GraphQL, la syntaxe vous paraîtra probablement familière, mais pas entièrement parseable. C’est normal. La Langue de définition de schéma (SDL) est concise, mais elle contient beaucoup de sens par ligne. Cet article la décompose afin que vous puissiez lire et écrire des schémas sans avoir besoin de consulter les documents toutes les cinq minutes.

Ce que est réellement un schéma GraphQL

Un schéma GraphQL est le contrat entre votre serveur API et chaque client qui l'appelle. Il définit exactement quelles données existent, quels opérations sont disponibles et quelle forme prennent les réponses. Contrairement au REST — où vous découvrez les points d'accès par documentation, essais et erreurs — le GraphQL rend le contrat explicite et lisible par les machines.

Chaque API GraphQL commence par un schéma écrit en SDL. Le serveur valide toutes les requêtes contre ce schéma en temps réel. Si un client demande un champ qui n'existe pas dans le schéma, la requête est rejetée avant que n'ait lieu aucun résolveur. C'est la valeur fondamentale du système de types de GraphQL : le schéma est la source de vérité pour la surface de l'API.

Principes de l'SDL : types, requêtes et mutations

Chaque fichier SDL est construit à partir de définitions de types. Voici le schéma le plus simple utile possible :

type Query {
  hello: String
}

Query est l'entrée pour les opérations de lecture. Chaque schéma doit en avoir un. Le champ hello renvoie un String — l'un des cinq types scalaires intégrés.

Les cinq scalaires intégrés sont :

  • String — texte UTF-8
  • Int — entier signé de 32 bits
  • Float — nombre à virgule flottante de précision double
  • Boolean — vrai ou faux
  • ID — un identifiant unique, sérialisé sous forme de chaîne

Les schémas réels définissent des types d'objets personnalisés. Voici un modèle plus typique :

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!]!
}

Beaucoup se passe dans ces 20 lignes. Examinons-le.

Champs non nuls et listes

Le ! après un type signifie que le champ est non nul — il ne retournera jamais null. Sans cela, le champ est nullable et le client doit gérer une valeur manquante. Cette distinction est importante en temps réel : si un résolveur de champ non nul lance une exception ou retourne null, GraphQL propage cette null vers l'arbre, potentiellement annulant les champs parents.

Les listes utilisent des crochets : [Post] est une liste nullable de posts nullable. [Post!]! est une liste non nulle de posts non nuls. C'est la version que vous voulez généralement — un champ qui retourne toujours un tableau (peut-être vide), et chaque élément de ce tableau est toujours un objet réel, pas null.

Les quatre combinaisons, exprimées :

  • [Post] — liste nullable, éléments nullable (très peu utile)
  • [Post!] — liste nullable, éléments non nuls
  • [Post]! — liste non nulle, éléments nullable
  • [Post!]! — liste non nulle, éléments non nuls (la plus courante)

Mutations : écriture de données

Les requêtes sont uniquement de lecture. Les mutations gèrent les écritures. Le type Mutation est structuré de la même manière que Query, mais par convention, ses champs ont des effets secondaires :

type Mutation {
  createPost(input: CreatePostInput!): Post!
  deletePost(id: ID!): Boolean!
}

Avis CreatePostInput! — c'est un type d'entrée, qui mène directement à la prochaine notion.

Types d'entrée vs types de sortie

C'est l'un des points les plus fréquents de confusion dans les schémas GraphQL. Vous ne pouvez pas réutiliser un type d'objet comme Post en tant que paramètre d'une mutation. SDL a deux types distincts pour une raison :

  • Types d'objets (type) — utilisés dans les réponses. Peuvent contenir des résolveurs et des logiques complexes de champs.
  • Types d'entrée (input) — utilisés dans les arguments. Données simples, sans résolveurs. Les champs ne peuvent référencer que des scalaires ou d'autres types d'entrée.
input CreatePostInput {
  title: String!
  body: String
  authorId: ID!
}

Cette séparation maintient une validation des arguments propre et empêche les problèmes de références circulaires qui surgiraient si les types de sortie (qui peuvent se référer les uns aux autres dans des graphes complexes) étaient utilisés directement en tant que types d'entrée.

Scalaires personnalisés

Les cinq scalaires intégrés ne couvrent pas tout. Une chaîne de date-heure, une URL, un blob JSON — ces éléments nécessitent des scalaires personnalisés. Vous les déclarez comme suit :

scalar DateTime
scalar JSON
scalar URL

La déclaration du scalaire indique le nom à utiliser. La logique de sérialisation, déserialisation et validation se trouve dans l'implémentation du serveur — pas dans le fichier de schéma. Des bibliothèques comme graphql-scalars offrent des implémentations prêtes à l'emploi pour des types courants afin que vous n'ayez pas à les écrire de zéro.

Utilisez des scalaires personnalisés lorsque String est techniquement correct mais sémantiquement erroné. Un champ typé comme DateTime communique l'intention ; un champ typé comme String force le client à deviner le format.

Enums

Les enums restreignent un champ à un ensemble fixe de valeurs de chaîne. Ils sont plus fiables que des chaînes brutes car le schéma impose les valeurs autorisées au niveau du type :

enum UserRole {
  ADMIN
  EDITOR
  VIEWER
}

enum PostStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}

Un champ typé comme UserRole ne retournera jamais une chaîne inattendue. Un champ typé comme String pourrait retourner n'importe quoi. Utilisez les enums chaque fois que l'ensemble des valeurs est connu, stable et significatif pour les clients — cela rend l'introspection du schéma beaucoup plus utile.

Interfaces et unions

Lorsqu'un champ peut retourner différents types d'objets, GraphQL propose deux mécanismes : les interfaces et les unions.

Interfaces définissent un ensemble partagé de champs. Les types qui implémentent l'interface doivent inclure ces champs :

interface Node {
  id: ID!
}

type User implements Node {
  id: ID!
  name: String!
}

type Post implements Node {
  id: ID!
  title: String!
}

Unions regroupent des types sans exiger de champs partagés. Ils sont utiles lorsque les types possibles n'ont rien de structurellement en commun :

union SearchResult = User | Post | Comment

type Query {
  search(query: String!): [SearchResult!]!
}

Les clients utilisent des fragments inline pour gérer chaque type dans une union ou une interface : ... on User { name }. Si vous retournez des données polymorphes, privilégiez les interfaces lorsque les types partagent des champs, et les unions lorsque ce n'est pas le cas.

Directives

Les directives modifient le comportement au niveau du champ ou du type. Deux sont intégrées dans chaque implémentation GraphQL :

  • @deprecated(reason: "Use newField instead") — marque un champ comme déprécié dans l'introspection
  • @skip(if: Boolean) et @include(if: Boolean) — conditions côté client dans les requêtes

Vous pouvez également définir des directives personnalisées pour des choses comme des gardes d'authentification, des indices de limitation de vitesse ou des annotations de mise en cache. Elles sont déclarées dans le schéma et implémentées sur le serveur :

directive @auth(requires: UserRole = ADMIN) on FIELD_DEFINITION

type Mutation {
  deleteUser(id: ID!): Boolean! @auth(requires: ADMIN)
}

GraphQL vs REST : Quand choisir lequel

L'approche schéma première de GraphQL se révèle bénéfique dans des situations spécifiques. C'est la bonne solution lorsque :

  • Plusieurs clients (web, mobile, tiers) ont besoin de sous-ensembles différents des mêmes données
  • Vous souhaitez évoluer l'API sans versionnement — ajouter des champs librement, dépréciés plutôt que supprimés
  • Le domaine est naturellement structuré comme un graphe avec des relations complexes entre les entités
  • Vous souhaitez une API auto-documentée que les clients peuvent explorer via l'introspection

Le REST reste la meilleure option lorsque :

  • Vous construisez des points d'accès simples CRUD avec des charges prévisibles et planes
  • Le cache HTTP est critique — les requêtes POST GraphQL ne sont pas cachées par défaut
  • L'équipe est petite et la surface de l'API est stable — l'overhead du REST est plus faible
  • Vous rencontrez le problème N+1 et que vous ne souhaitez pas configurer DataLoader pour le résoudre

Le problème N+1 mérite d'être mis en pause. Dans un résolveur GraphQL qui récupère posts et chaque post de author, une implémentation naïve lance une requête de base pour chaque post afin de charger l'auteur. Avec 50 posts, cela donne 51 requêtes pour une seule requête. Le REST n'a pas ce problème car vous contrôlez exactement quel SQL est exécuté par point d'accès. Dans GraphQL, vous le résolvez avec le batch (DataLoader ou équivalent) — c'est résolvable, mais c'est une autre chose à configurer correctement.

Formatez et validez votre SDL

Les fichiers de schéma accumulent des indentations incohérentes, des espaces mal placés et des dérives structurelles au fur et à mesure que les équipes grandissent. Avant de commiter des modifications de schéma, passez-les par un formateur afin de normaliser les espaces, de trier les champs et de détecter les erreurs de syntaxe avant qu'elles ne touchent le CI.

Le Formatteur de schéma GraphQL on iotools.cloud fait exactement cela — collez votre SDL, obtenez un résultat propre, formatté de manière cohérente, avec des erreurs de validation affichées en ligne. Il gère les schémas multi-types, les scalaires personnalisés, les directives et les cas limites qui empêchent une mise en forme manuelle. Utile comme étape finale avant de commiter ou de partager un schéma avec une autre équipe.

Envie d'une expérience sans pub ? Passez à la version sans pub

Installez nos extensions

Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide

Sur Extension Chrome Sur Extension de bord Sur Extension Firefox Sur Extension de l'opéra

Le Tableau de Bord Est Arrivé !

Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !

ANNONCE · Supprimer ?
ANNONCE · Supprimer ?
ANNONCE · Supprimer ?

Coin des nouvelles avec points forts techniques

Impliquez-vous

Aidez-nous à continuer à fournir des outils gratuits et précieux

Offre-moi un café
ANNONCE · Supprimer ?