Données structurées
Mis à jour le 30 juillet 2026
Le problème
Ce chapitre résout un problème très concret : la sortie d’un modèle est faite pour être lue par un humain, alors que votre code, lui, veut la parser. Les deux exigences sont contradictoires — le texte d’accompagnement qui rend la réponse agréable est précisément ce qui fait échouer json.loads().
Quand vous demandez à Claude de générer du JSON, du code ou tout autre format structuré, il a tendance à envelopper sa réponse dans du texte explicatif :
Voici la configuration JSON que vous avez demandee :
```json
{"server": "nginx", "port": 80}
N’hesitez pas a adapter les valeurs selon vos besoins !
C'est très bien pour un humain qui lit la réponse. Mais c'est un cauchemar pour du code qui doit **parser** la sortie. Un `json.loads()` sur ce texte va échouer immédiatement.
## La solution : prefill + stop séquence
En combinant les deux techniques vues dans la leçon précédente, on peut extraire **uniquement** le contenu structuré :
1. **Prefill** : on commence la réponse avec le marqueur d'ouverture (ex: ` ```json\n`)
2. **Stop sequence** : on arrête Claude au marqueur de fermeture (ex: ` ``` `)
Claude ne peut plus ajouter de texte avant ou après -- il est contraint de produire directement le contenu structuré.
## Exemple concret : générer une règle EventBridge AWS
```python
import anthropic
import json
client = anthropic.Anthropic()
def generer_json(description):
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": f"Génère une regle AWS EventBridge en JSON pour : {description}"
},
{
"role": "assistant",
"content": "```json\n"
}
],
stop_sequences=["```"]
)
texte_brut = response.content[0].text
return json.loads(texte_brut.strip())
# Utilisation
regle = generer_json("Détecter les arrêts d'instances EC2")
print(json.dumps(regle, indent=2))
Résultat :
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["stopped", "stopping"]
}
}
Pas de texte parasite. Du JSON pur, directement parseable.
Comment ça marche, étape par étape
- L’utilisateur demande une règle EventBridge
- Le prefill
\“json\n` indique à Claude qu’il est déjà dans un bloc de code JSON - Claude génère le contenu JSON
- Dès que Claude produit
\“ ` pour fermer le bloc, la stop séquence l’arrête - On récupère uniquement le JSON, qu’on parse avec
json.loads()
Le strip() est une précaution : il supprime les espaces ou sauts de ligne en début/fin de chaîne.
Au-delà du JSON
Cette technique fonctionne pour tout format structuré. L’idée clé est toujours la même : identifier ce que Claude utilise pour envelopper le contenu, puis utiliser ces enveloppes comme prefill et stop séquence.
Code Python
def generer_python(description):
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": f"Écris une fonction Python qui : {description}"
},
{
"role": "assistant",
"content": "```python\n"
}
],
stop_sequences=["```"]
)
return response.content[0].text.strip()
code = generer_python("calcule la suite de Fibonacci jusqu'a n")
print(code)
CSV
def generer_csv(description):
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": f"Génère des données CSV : {description}"
},
{
"role": "assistant",
"content": "```csv\n"
}
],
stop_sequences=["```"]
)
return response.content[0].text.strip()
csv_data = generer_csv("5 villes françaises avec population et region")
print(csv_data)
Liste simple
def generer_liste(description, n=5):
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": f"Donne une liste de {n} elements : {description}"
},
{
"role": "assistant",
"content": "1. "
}
],
stop_sequences=[f"{n + 1}. "]
)
return "1. " + response.content[0].text.strip()
liste = generer_liste("langages de programmation pour le web", 5)
print(liste)
L’idée clé à retenir
Prenez un moment sur ce point, car il se transpose bien au-delà du JSON. La technique ne repose sur aucune fonctionnalité particulière de l’API : elle exploite le fait que le modèle emballe toujours le contenu structuré de la même façon. Dès lors que vous savez quels marqueurs il emploie, vous pouvez vous en servir comme bornes — c’est ce qui rend le tableau ci-dessous extensible à n’importe quel format que vous rencontrerez. Quand on lui demande du JSON, il écrit ```json ... ```. Quand on lui demande du code, il écrit ```python ... ```.
En utilisant ces marqueurs comme prefill (début) et stop séquence (fin), on isole parfaitement le contenu structuré du texte explicatif.
| Format | Prefill | Stop séquence |
|---|---|---|
| JSON | ```json\n | ``` |
| Python | ```python\n | ``` |
| CSV | ```csv\n | ``` |
| XML | <root> | </root> |
| Liste numérotée | 1. | {n+1}. |
Attention
Dernier point avant de passer à la suite : cette technique contraint le format, jamais le contenu. Vous obtiendrez du JSON syntaxiquement valide, pas nécessairement du JSON dont les valeurs sont correctes. Le try/except autour du parsing reste indispensable — un modèle peut produire un objet bien formé et pourtant incomplet sur une demande ambiguë.
- Utilisez toujours
strip()avant de parser, pour éliminer les espaces parasites - Testez avec plusieurs inputs : Claude peut parfois générer du JSON invalide sur des requêtes ambiguës
- Pour des structures JSON complexes, ajoutez un exemple dans le prompt utilisateur