Les trois fenêtres de chat aiment le langage naturel ; les trois docs d'API écrivent le contrat en JSON. Ce texte est daté du 2026-09-05 : on ne parie pas sur le format de la génération suivante, on écrit uniquement les chemins déjà en production — OpenAI Structured Outputs, output_config / input_schema chez Claude, responseSchema chez Gemini, et le JSON-RPC de MCP. D'abord « pourquoi le JSON », puis les trois enveloppes, enfin un échantillon inter-plateformes qui fait pousser un Schema.
« Aimer le JSON » sonne comme un goût. Pour le modèle, c'est : l'interface peut-elle être rattrapée par le saut suivant. Un humain peut lire un français fluide ; une base, un front, la facturation et la boucle Agent, non. Les phares 2026 — GPT-5.6, Claude Fable 5.1, Gemini 3.8 Flash — n'ont pas la même gamme, voir l'article précédent Guerre des modèles 2026, mais pour remettre le résultat à un programme, ils prennent tous le même chemin : un objet parseable, plus un Schema.
Ce que le modèle veut vraiment, ce n'est pas les accolades
Le texte libre convient à l'explication. Il ne convient pas comme contrat. Un guillemet manquant, true écrit « oui », un montant écrit « environ 12 euros » : l'aval doit écrire des regex, des retries, un filet humain. Le JSON n'a pas été choisi parce que la RFC 8259 est élégante, mais parce qu'il tient quatre choses à la fois :
- Ça parse. Chaque langage, chaque SDK, le navigateur ont un parseur tout prêt. L'échec est une erreur de syntaxe, pas un « ça ne sent pas juste ».
- Ça se valide. JSON Schema sait écrire type, enum,
required,additionalProperties. Le modèle peut être contraint à la génération ; le serveur peut revérifier. - Ça s'imbrique. Objet, tableau, booléen, nombre, null couvrent les paramètres d'outil et les pièces métier. Pas besoin d'inventer un nouvel arbre.
- C'est partout dans l'entraînement. Réponses d'API, fichiers de config, logs,
application/jsondans les pages : le modèle a vu bien plus de JSON valide que de YAML ou d'XML valide.
YAML est allergique à l'indentation ; commentaires et documents multiples font encore bifurquer le parseur. XML a des balises lourdes ; les namespaces allongent le Schema. Un tableau Markdown se lit, ce n'est pas une entrée de programme. Les trois écrivent donc « structuré » ainsi : la sortie doit être du JSON, et la forme doit coller au Schema.
La forme peut coller, la valeur peut encore être fausse. Le décodage contraint garantit les clés et les types, pas « prix unitaire × quantité = total ». La doc Google le dit sans détour. Ça vaut pour les trois : le Schema passe, les règles métier se revérifient.
Chat, API, outils : les trois couches convergent
Un même produit a en réalité trois couches de sortie. Les mélanger, et l'on a l'impression que « le modèle obéit parfois, parfois non ».
| Couche | Pour l'humain | Pour le programme |
|---|---|---|
| Fenêtre de chat | Explications, brouillons, phrases avec un ton | Presque aucun contrat ; coller, c'est encore retoucher à la main |
| Structured Output | Peut être absent | Toute la réponse est un objet JSON |
| Function Calling / outils | Le modèle dit « je vais appeler cet outil » | Les paramètres doivent coller à parameters / input_schema |
En 2024, on tenait encore avec le prompt « renvoyez uniquement du JSON ». En 2026, cette voie est une dette. JSON Mode garantit seulement que les accolades parsent, pas que les champs sont là. Le chemin de production, c'est le décodage contraint : les tokens illégaux sont bloqués à l'échantillonnage. Pour la méthode, voir Générer un Structured Output depuis un échantillon ; pour la boucle d'outils côté Agent, voir DevDay 2026 Agent.
Comment chacune « aime » le JSON
Ce qu'elles aiment, c'est le même objet, pas le même corps de requête. Écrivez l'enveloppe dans la doc, laissez les champs dans un fichier partagé.
1. ChatGPT / OpenAI : le Schema entre dans le décodeur
Dans Chat Completions, Structured Outputs se raccroche à response_format, type json_schema ; en production, ouvrez strict: true. Responses API pose le même objet dans text.format. Coller les champs d'un ancien guide sur la nouvelle API ne produit souvent pas une belle erreur : ça cesse simplement de contraindre comme vous le pensiez. Le .parse() du SDK le reprend encore une fois via Pydantic / Zod.
Côté outils, c'est un autre contrat : les parameters de la fonction sont aussi du JSON Schema. Programmatic Tool Calling laisse le modèle enchaîner plusieurs tours d'outils côté serveur ; ce qui entre et sort reste un objet, pas de la prose. JSON Mode (ça parse, c'est tout) peut rester en démo ; pas sur le chemin de facturation ni d'écriture.
2. Claude : les paramètres d'outil sont le contrat
Anthropic écrit « donnez-moi un objet » et « allez appeler un outil » avec la même forme. Pour du JSON direct, Messages API : output_config.format (l'ancien nom output_format est déprécié). Sur le chemin Agent, on ajoute input_schema à l'outil, et on ouvre strict: true sur la définition d'outil — pas sur tool_choice.
Le Schema exige aussi additionalProperties: false et un required complet. En échange : l'outil que le modèle choisit a ses paramètres contraints à la génération. Le client.messages.parse() du SDK valide pour vous ; il ne livre pas la chaîne brute au métier.
3. Gemini : mime type plus Schema
Gemini rassemble JSON Mode et Structured Output en une seule ligne : response_mime_type: application/json, plus responseSchema / response_json_schema. C'est celui qui a l'air le plus « Schema natif », et le sous-ensemble le plus étroit : types de base, enum, format, bornes, required passent ; polymorphisme profond, $ref récursifs, arbres trop grands ou trop profonds — la doc dit qu'elle peut refuser net.
Pour du Structured Output à haut volume, on choisit encore souvent Gemini 3.8 Flash, voir Choisir un modèle par tâche. Plafond de sortie 64K ; découpez d'abord les longs documents. Gemini 4 n'a pas de date de sortie ; le chemin de production s'écrit encore en 3.x, détail dans Quand sort Gemini 4.
Un cran plus loin : MCP, évaluations, routage
Au-delà des éditeurs de modèles, le JSON est déjà le bus du runtime Agent.
- MCP décrit les outils en JSON-RPC. Nom d'outil, paramètres, valeur de retour : des objets. La page MCP Tool de ce site écrit ce contrat, pas un prompt.
- Évaluations et traces doivent pouvoir passer au Diff. Une prose ne se compare pas automatiquement ; un JSON, via la Comparaison JSON, montre si un champ a dérivé ou si un type a dérivé.
- Le routage de modèles peut lui-même être du JSON : tâche, contraintes,
model_idcandidats, raison du choix. L'article précédent a déjà donné un échantillon de routage. Au changement de génération, on change l'ID, pas les noms de champs.
Donc « le JSON devient le format de données universel de l'IA » n'est pas un slogan. Ça veut dire : le prompt peut être du langage naturel ; la frontière doit être un objet. Qui génère l'objet peut changer ; à quoi l'objet ressemble ne se négocie pas à l'oral.
Format universel ne veut pas dire « n'importe quel JSON »
Traiter n'importe quelles accolades comme un contrat, et ça explose quand même dans trois mois. Le JSON qui survit d'un modèle à l'autre a d'ordinaire cinq règles dures :
- Types figés. Un booléen est
true/false, pas « yes ». Un nombre est number, pas"0.75". - Énumérations refermées. Statut, raison, priorité : enum. Le texte libre reste pour les phrases vraiment destinées à s'afficher.
requiredlisté en entier. Les trois modes stricts exigent que vous listiez explicitement les champs obligatoires. Oublier une entrée, c'est autoriser un champ manquant.additionalProperties: false. Sinon le modèle invente des clés que votre parseur ne connaît pas.- Un échantillon, trois enveloppes. Les champs ne se maintiennent qu'une fois. Les corps de requête OpenAI / Claude / Gemini se génèrent depuis le même Schema.
Le langage Schema de Gemini est un sous-ensemble OpenAPI. Partez de l'intersection : objet, tableau, string / number / integer / boolean, enum, required. Gardez oneOf, les références récursives et l'imbrication trop profonde pour plus tard, une fois que vous avez confirmé que la plateforme les avale.
Un échantillon qui marche chez les trois
Voici le JSON métier de « extraire une facture ». Ce n'est pas l'enveloppe de requête ; c'est l'objet que les trois modèles devraient produire. Énumérations en chaînes, montants en number, taxe incluse ou non en boolean.
{
"doc_type": "invoice",
"currency": "CNY",
"vendor": "Example Labs",
"invoice_id": "INV-20260905-018",
"issued_on": "2026-09-05",
"line_items": [
{
"sku": "schema-review",
"qty": 2,
"unit_price": 480,
"amount": 960
}
],
"subtotal": 960,
"tax": 96,
"total": 1056,
"tax_included": false,
"confidence": 0.86,
"needs_review": false
}
Selon les règles d'inférence actuelles du site, cet échantillon donne :
| Champ | Type inféré | À faire après génération |
|---|---|---|
doc_type / currency |
string | Refermer en enum, ne pas laisser de texte libre |
qty / montants / confidence |
number | Écrire "960" dérive en string ; ajoutez à confidence une borne 0–1 |
tax_included / needs_review |
boolean | L'échantillon doit être true / false |
line_items |
array of object | Chaque élément doit avoir sku, qty, amount |
issued_on |
string | Ajoutez format: date ; ne laissez pas le modèle écrire « 5 septembre » |
Échantillon prêt : ouvrez Structured Output pour générer les trois enveloppes OpenAI / Claude / Gemini, puis relisez à la main required et additionalProperties. Le même objet peut aussi devenir un outil, via Function Calling : le modèle ne « parle pas d'une facture », il soumet une pièce qui doit pouvoir se valider.
Recetter dans la Boîte à outils JSON
- Collez l'échantillon ci-dessus dans le formatage JSON, pour confirmer que ça parse.
- Générez le brouillon avec Structured Output ou JSON → Schema.
- Passez un second vrai résultat de modèle dans la validation Schema. Le premier échantillon est toujours trop propre.
- Au passage de GPT à Claude ou Gemini, utilisez la Comparaison JSON pour voir si un champ a disparu ou si un type a dérivé.
- Validation front : Zod ; doc d'API si besoin : OpenAPI 3.1.
Tout se traite dans le navigateur, rien n'est envoyé au serveur.
FAQ
Pourquoi les grands modèles aiment-ils tous sortir du JSON, plutôt que du YAML ou de l'XML ?
Les parseurs, l'écosystème Schema et le corpus d'entraînement tiennent le JSON. YAML craint l'indentation, XML est trop lourd. Les trois contrats s'écrivent en JSON Schema.
Quelle est la différence entre JSON Mode et Structured Output ?
JSON Mode garantit seulement que ça parse. Structured Output fait un décodage contraint selon le Schema. En production, on prend le second.
Les trois peuvent-elles partager un même Schema ?
Les champs se partagent ; les enveloppes, non. Générez les trois corps de requête depuis le même échantillon.
Un Schema valide, est-ce que ça veut dire que le métier est juste ?
Non. La forme peut coller, le total peut encore être faux. Un second jeu de sorties réelles doit se revérifier.
Faut-il réécrire le contrat JSON quand on change de modèle ?
Non. Figez les champs, changez model_id et l'enveloppe. Le routage lui-même peut être du JSON, voir Guerre des modèles 2026.
En résumé
ChatGPT, Claude et Gemini aiment le JSON parce qu'un programme doit rattraper le modèle, pas s'appuyer sur un bon article. Les trois enveloppes diffèrent : response_format / text.format, output_config / input_schema, responseSchema. Ce qui se partage : les champs, les types, les obligatoires, et « pas de clé en trop ». MCP, évaluations et routage passent aussi par des objets. Ce qui survit au changement de génération de la semaine suivante, c'est l'échantillon et le Schema, pas le « renvoyez du JSON » du prompt. Un seul échantillon fait pousser le contrat ; validation, Zod et OpenAPI le suivent.