← Tous les articles

Qu'est-ce que JSON Schema ? Un guide pratique avec exemples

JSON Schema est un vocabulaire pour décrire la structure et les contraintes des données JSON. Apprenez les mots-clés centraux, voyez des exemples réels et validez du JSON en JavaScript, Python et votre navigateur.

JSON Schema est un vocabulaire pour décrire la structure, les contraintes et les types d'un document JSON. Il permet de définir exactement à quoi doit ressembler un JSON valide — quelles clés sont obligatoires, quel type chaque valeur doit avoir, quelles valeurs sont autorisées — puis de valider automatiquement n'importe quel document JSON par rapport à ces règles. Ce guide explique ce qu'est JSON Schema, comment en écrire un, et comment l'utiliser pour valider du JSON en JavaScript, Python et dans le navigateur.

Qu'est-ce que JSON Schema ?

JSON Schema est lui-même un document JSON. Il décrit un autre document JSON de la même manière qu'un schéma de base de données décrit une table : il déclare la forme attendue, les types et les contraintes des données. Un JSON Schema dit aux validateurs — bibliothèques, APIs, générateurs de formulaires, IDE — ce que « valide » signifie pour un morceau particulier de JSON.

La spécification est maintenue sur json-schema.org et est actuellement au Draft 2020-12. Il est utilisé par OpenAPI (le standard pour documenter les APIs REST), JSON Forms (génération d'UI depuis des schémas), l'outillage IDE (VS Code utilise JSON Schema pour propulser l'autocomplétion dans package.json et tsconfig.json) et d'innombrables pipelines de données internes.

Un exemple minimal de JSON Schema

Voici un document JSON représentant un utilisateur, suivi d'un schéma qui décrit sa structure attendue :

// Le document JSON à valider
{
  "id": 42,
  "name": "Alice",
  "email": "alice@example.com",
  "age": 30,
  "active": true
}
// Le JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id":     { "type": "integer" },
    "name":   { "type": "string", "minLength": 1 },
    "email":  { "type": "string", "format": "email" },
    "age":    { "type": "integer", "minimum": 0, "maximum": 150 },
    "active": { "type": "boolean" }
  },
  "additionalProperties": false
}

Ce schéma dit : le document doit être un objet ; id, name et email sont obligatoires ; age doit être compris entre 0 et 150 s'il est présent ; et aucune autre clé que les cinq listées n'est autorisée.

Les mots-clés principaux

type

Spécifie le type JSON d'une valeur. Les types valides sont "string", "number", "integer", "boolean", "array", "object" et "null". Vous pouvez autoriser plusieurs types avec un tableau :

{ "type": ["string", "null"] }  // la valeur peut être une chaîne ou null

properties

Définit le schéma de chaque clé d'un objet. Chaque entrée est elle-même un schéma :

{
  "type": "object",
  "properties": {
    "firstName": { "type": "string" },
    "lastName":  { "type": "string" },
    "age":       { "type": "integer", "minimum": 0 }
  }
}

required

Un tableau de noms de clés qui doivent être présents dans l'objet. Une clé listée sous properties mais pas dans required est optionnelle — elle peut être absente, mais si elle est présente elle doit correspondre à son schéma.

items

Définit le schéma pour chaque élément d'un tableau. Ce schéma exige un tableau de chaînes :

{
  "type": "array",
  "items": { "type": "string" }
}

Contraintes sur les chaînes

{
  "type": "string",
  "minLength": 1,
  "maxLength": 100,
  "pattern": "^[a-zA-Z0-9_]+
quot; // motif regex }

Contraintes numériques

{
  "type": "number",
  "minimum": 0,
  "maximum": 1,
  "multipleOf": 0.01   // doit être un multiple de 0.01
}

enum

Restreint une valeur à un ensemble fixe de valeurs autorisées :

{ "enum": ["pending", "active", "suspended", "deleted"] }

additionalProperties

Contrôle si les clés non listées dans properties sont autorisées. Mettez-le à false pour rejeter toute clé inattendue — utile pour les contrats d'API stricts :

{ "additionalProperties": false }

Un exemple réel de JSON Schema

Voici un schéma pour un produit dans une API d'e-commerce — du genre qu'on voit dans une définition OpenAPI ou un contrat de données interne :

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/schemas/product.json",
  "title": "Product",
  "description": "A product available for purchase",
  "type": "object",
  "required": ["id", "name", "price", "category"],
  "properties": {
    "id": {
      "type": "integer",
      "description": "Unique product identifier"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "price": {
      "type": "number",
      "minimum": 0,
      "description": "Price in USD"
    },
    "category": {
      "type": "string",
      "enum": ["electronics", "clothing", "books", "home", "sports"]
    },
    "tags": {
      "type": "array",
      "items": { "type": "string" },
      "uniqueItems": true
    },
    "dimensions": {
      "type": "object",
      "properties": {
        "width":  { "type": "number", "minimum": 0 },
        "height": { "type": "number", "minimum": 0 },
        "depth":  { "type": "number", "minimum": 0 }
      },
      "required": ["width", "height", "depth"]
    },
    "inStock": { "type": "boolean" }
  },
  "additionalProperties": false
}

Comment valider du JSON contre un schéma

Vous cherchez un validateur jsonschema ? Les choix standards sont Ajv (JavaScript), jsonschema (Python) et des services en ligne comme jsonschemavalidator.net. Si vous avez besoin du sens inverse — générer un json schema depuis un exemple, ou un json schema depuis un document json — essayez GenSON en Python ou transform.tools dans le navigateur. Ce sont des outils json schema generator qui déduisent un schéma de départ depuis un échantillon. Ensuite, resserrez à la main required, additionalProperties et les contraintes sur les valeurs.

En JavaScript (Ajv)

Ajv est le validateur JSON Schema le plus utilisé dans l'écosystème JavaScript. Il prend en charge Draft-07 et Draft 2020-12.

npm install ajv
import Ajv from 'ajv';

const ajv = new Ajv();

const schema = {
  type: 'object',
  required: ['id', 'name', 'email'],
  properties: {
    id:    { type: 'integer' },
    name:  { type: 'string', minLength: 1 },
    email: { type: 'string' },
  },
  additionalProperties: false,
};

const validate = ajv.compile(schema);

const data = { id: 42, name: 'Alice', email: 'alice@example.com' };
const valid = validate(data);

if (!valid) {
  console.error(validate.errors);
} else {
  console.log('Valid!');
}

ajv.compile(schema) renvoie une fonction validate réutilisable. Compiler une seule fois et appeler le résultat à plusieurs reprises est nettement plus rapide que recompiler à chaque appel.

En JavaScript (navigateur, sans dépendances)

Pour des vérifications simples de type et de champ obligatoire sans ajouter de dépendance, vous pouvez valider à la main — mais pour tout ce qui dépasse les vérifications triviales, utilisez Ajv. La logique de validation de schéma est suffisamment complexe pour que la coder à la main soit source d'erreurs.

En Python (jsonschema)

pip install jsonschema
import json
import jsonschema
from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "required": ["id", "name", "email"],
    "properties": {
        "id":    {"type": "integer"},
        "name":  {"type": "string", "minLength": 1},
        "email": {"type": "string"},
    },
    "additionalProperties": False,
}

data = {"id": 42, "name": "Alice", "email": "alice@example.com"}

try:
    validate(instance=data, schema=schema)
    print("Valid!")
except ValidationError as e:
    print(f"Invalid: {e.message}")

Valider un fichier JSON contre un schéma

import json
import jsonschema

with open('schema.json') as f:
    schema = json.load(f)

with open('data.json') as f:
    data = json.load(f)

jsonschema.validate(instance=data, schema=schema)

Dans le navigateur (fixjson)

Si vous devez vérifier qu'un document JSON est structurellement valide avant de travailler avec — sans écrire de code — le validateur JSON de fixjson vérifie la syntaxe et signale les erreurs instantanément. Collez votre JSON et les éventuels problèmes de syntaxe apparaissent en ligne avec la ligne et la position exactes de chaque erreur.

Pour une validation complète de schéma (vérification des types, des champs obligatoires, des contraintes), utilisez l'une des approches basées sur bibliothèque ci-dessus, ou un outil dédié comme jsonschemavalidator.net.

$ref : réutiliser des schémas

Les vrais schémas ne définissent pas tout en ligne. Le mot-clé $ref permet de référencer un autre schéma par son $id ou par un chemin JSON Pointer dans le même document, ce qui garde les schémas DRY et composables.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "address": {
      "type": "object",
      "required": ["street", "city", "country"],
      "properties": {
        "street":  { "type": "string" },
        "city":    { "type": "string" },
        "country": { "type": "string", "minLength": 2, "maxLength": 2 }
      }
    }
  },
  "type": "object",
  "properties": {
    "billingAddress":  { "$ref": "#/$defs/address" },
    "shippingAddress": { "$ref": "#/$defs/address" }
  }
}

$defs est l'emplacement standard pour définir des sous-schémas réutilisables dans un même fichier (il a remplacé definitions au Draft 2019-09).

Combiner des schémas : allOf, anyOf, oneOf

JSON Schema dispose de trois mots-clés de composition pour exprimer « doit satisfaire tous », « doit satisfaire au moins un » et « doit satisfaire exactement un » :

// allOf : doit satisfaire chaque schéma listé
{
  "allOf": [
    { "type": "object" },
    { "required": ["id"] },
    { "properties": { "id": { "type": "integer" } } }
  ]
}

// anyOf : doit satisfaire au moins un schéma
{
  "anyOf": [
    { "type": "string" },
    { "type": "null" }
  ]
}

// oneOf : doit satisfaire exactement un schéma (ils doivent être mutuellement exclusifs)
{
  "oneOf": [
    { "properties": { "type": { "const": "circle" } }, "required": ["radius"] },
    { "properties": { "type": { "const": "rectangle" } }, "required": ["width", "height"] }
  ]
}

Le mot-clé format : date-time, email, uri, uuid

Au-delà des types bruts, le mot-clé format de JSON Schema annote les chaînes avec leur forme attendue — une date-time ISO, une adresse e-mail, un URI, un UUID, une adresse IP, et ainsi de suite. Cela ressemble à ceci :

{
  "type": "object",
  "properties": {
    "id":         { "type": "string", "format": "uuid" },
    "created_at": { "type": "string", "format": "date-time" },
    "email":      { "type": "string", "format": "email" },
    "homepage":   { "type": "string", "format": "uri" }
  }
}

Un point subtil mais important : dans Draft 2020-12 (et 2019-09), le mot-clé format est une annotation par défaut — il n'applique pas le format à moins que le validateur ne soit configuré pour le faire. Dans Draft-07 et antérieurs, c'était une assertion par défaut dans certains validateurs. Pour le rendre strict dans Ajv :

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);              // enregistre date-time, email, uri, uuid, etc.

// En 2020-12, il faut activer l'assertion de format dans votre méta-schéma
// ou passer explicitement { validateFormats: true }, selon la version d'Ajv.

Valeurs format courantes : date-time, date, time, duration, email, idn-email, hostname, ipv4, ipv6, uri, uri-reference, uuid, regex, json-pointer.

Traitez format comme un indice, pas comme une frontière de sécurité — une chaîne qui passe format: "email" reste un input non fiable. Pour la délivrabilité ou la validité réelle, vérifiez hors-bande (DNS, envoi d'un e-mail de confirmation, exécution d'une regex que vous contrôlez).

Erreurs courantes en JSON Schema

Confondre « properties » et « required »

Lister une clé sous properties ne la rend pas obligatoire. Une clé dans properties définit le schéma de cette clé si elle apparaît. Pour imposer sa présence, vous devez aussi la lister dans required.

Utiliser « integer » quand vous voulez dire « number »

"type": "integer" rejette 3.14. Si votre champ peut être n'importe quel nombre (y compris décimaux), utilisez "type": "number".

Oublier que « additionalProperties » vaut true par défaut

Par défaut, JSON Schema autorise toute propriété additionnelle non listée sous properties. C'est intentionnel — les schémas sont conçus pour être ouverts par défaut, suivant la loi de Postel. Si vous voulez un objet fermé, définissez explicitement "additionalProperties": false.

Ne pas spécifier $schema

Les différents drafts ont des sémantiques différentes. Omettre le mot-clé $schema laisse les validateurs deviner quelle version utiliser. Incluez-le toujours :

{ "$schema": "https://json-schema.org/draft/2020-12/schema" }

Traiter la validation JSON Schema comme une validation de sécurité

JSON Schema valide la structure et les types — ce n'est pas un outil d'assainissement. Une chaîne qui passe "type": "string" pourrait toujours contenir de l'injection SQL, des payloads XSS ou d'autres contenus malveillants. La validation de schéma est un premier filtre, pas une mesure de sécurité complète.

JSON Schema et OpenAPI

OpenAPI (anciennement Swagger) utilise un sous-ensemble de JSON Schema pour décrire les corps de requête, de réponse et les paramètres. Si vous avez écrit une spec OpenAPI, vous avez écrit du JSON Schema — bien qu'OpenAPI utilise un dialecte modifié avec quelques extensions et restrictions.

Cela signifie que la connaissance de JSON Schema se transfère directement au design d'API. La section components/schemas d'un document OpenAPI est une collection de JSON Schemas, et des outils comme Stoplight, Redoc et Swagger UI les transforment automatiquement en documentation interactive.

Travailler avec Ajv en pratique

Deux options rentabilisent leur coût dans tout vrai projet :

  • strict: true (par défaut dans Ajv moderne) — rejette les mots-clés inconnus et les formats inconnus au moment de la compilation du schéma, attrapant les fautes de frappe comme "minimun" ou un $schema manquant avant qu'ils ne laissent passer silencieusement des données.
  • allErrors: true — collecte tous les échecs de validation au lieu de s'arrêter au premier. Se marie bien avec ajv.errorsText() pour des messages destinés aux utilisateurs.

Pour générer du faux JSON depuis un schéma pour des tests et des fixtures, utilisez json-schema-faker : il parcourt le schéma et produit des valeurs qui correspondent (types, plages, enums, et même format lorsqu'il est combiné à ajv-formats). Utile pour des tests basés sur les propriétés ou pour amorcer une UI depuis un schéma.

Générer un JSON Schema à partir de JSON existant

Si vous avez des données JSON et voulez en générer un schéma de départ, plusieurs outils automatisent le processus :

  • quicktype.io — déduit des schémas (et des définitions de type pour TypeScript, Go, Python, etc.) depuis un JSON d'exemple
  • generate-schema (npm) generate-schema json schema.json data.json
  • Python : gensonpip install genson, puis SchemaBuilder déduit un schéma depuis un ou plusieurs objets d'exemple

Les schémas générés sont un point de départ, pas un produit fini. Ils déduisent les types depuis les données d'exemple, mais ne connaissent pas vos règles métier — ils ne peuvent pas déduire qu'un champ string est une adresse e-mail, qu'un entier doit être positif, ou que deux champs sont mutuellement exclusifs. Revoyez et resserrez toujours un schéma généré avant de l'utiliser en production.

Foire aux questions

À quoi sert JSON Schema ?

À décrire et valider la structure de données JSON — quelles clés sont obligatoires, quel type chaque valeur doit avoir et quelles valeurs sont autorisées. Il fait tourner OpenAPI, l'autocomplétion IDE de package.json/tsconfig.json, la génération de formulaires et les contrats de pipelines de données.

Quelle est la différence entre JSON et JSON Schema ?

JSON, ce sont les données ; JSON Schema est un document JSON distinct qui décrit à quoi ressemblent les données valides. Si vous débutez avec le format lui-même, commencez par Qu'est-ce que JSON ?.

Quel draft JSON Schema devrais-je utiliser ?

Draft 2020-12 est l'actuel et le recommandé pour les nouveaux schémas ; Draft-07 reste répandu grâce à un large support d'outillage. Déclarez toujours la version avec $schema pour ne pas laisser les validateurs deviner.

Comment valider du JSON contre un schéma ?

Utilisez Ajv en JavaScript, la bibliothèque jsonschema en Python (exemples ci-dessus), ou un validateur web. Pour confirmer d'abord que le JSON est même syntaxiquement valide, voir Comment valider du JSON ou passez-le par le validateur.

JSON Schema valide-t-il format (email, date-time, uri…) ?

En Draft 2020-12 / 2019-09, le mot-clé format est une annotation par défaut — les validateurs ne l'imposent que s'ils sont configurés en ce sens. Avec Ajv, enregistrez ajv-formats et activez l'assertion de format pour réellement rejeter les valeurs mal formées.

Conclusion

JSON Schema transforme la documentation informelle (« ce champ devrait être un nombre ») en un contrat vérifiable par la machine que les validateurs peuvent faire respecter de façon cohérente entre langages, équipes et systèmes. Le vocabulaire central — type, properties, required, items, enum — couvre la grande majorité des cas d'usage réels. Des fonctionnalités plus avancées comme $ref, les mots-clés de composition et format s'occupent du reste.

Commencez par un schéma minimal qui n'impose que ce que vous avez véritablement besoin d'imposer. Ajoutez les contraintes de façon incrémentale à mesure que votre compréhension des données se solidifie. Un schéma qui rejette des données valides est pire que pas de schéma du tout.

Si le JSON que vous validez a des erreurs de syntaxe avant même d'atteindre le validateur de schéma, réparez-les d'abord — un validateur de schéma exige un JSON syntaxiquement correct en entrée. Une fois le JSON propre, validez-le puis appliquez votre schéma.