Python JSON
Apprenez à utiliser le module json de Python pour encoder, décoder, lire et écrire des données JSON, avec des exemples pratiques et la gestion des erreurs.
Le module intégré json de Python vous permet de convertir des objets Python en texte JSON avec seulement deux fonctions dans la plupart des cas. Ce chapitre couvre tout ce dont vous avez besoin : le mappage des types de données, dumps/loads pour les chaînes, dump/load pour les fichiers, l'affichage formaté, la gestion des erreurs et la sérialisation personnalisée.
Qu'est-ce que JSON ?
JSON (JavaScript Object Notation) est un format léger d'échange de données basé sur du texte. Il est lisible par l'homme, indépendant du langage, et constitue le format par défaut de la plupart des API web.
Un document JSON est construit à partir de deux structures :
- Les objets — collections non ordonnées de paires clé/valeur entourées de
{}. Les clés sont toujours des chaînes entre guillemets doubles. - Les tableaux (arrays) — séquences ordonnées de valeurs entourées de
[].
Exemple de document JSON :
{
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"],
"active": true,
"score": null
}Correspondance des types Python–JSON
Lors de l'encodage ou du décodage JSON, le module json de Python convertit les types selon ce tableau :
| Type Python | Type JSON | Type Python (après décodage) |
|---|---|---|
dict | object {} | dict |
list, tuple | array [] | list |
str | string "" | str |
int, float | number | int ou float |
True / False | true / false | bool |
None | null | None |
Notez que les tuples deviennent des tableaux JSON et reviennent sous forme de listes Python après le décodage.
Encoder des objets Python en chaînes JSON
json.dumps() (dump-string) sérialise un objet Python en une chaîne au format JSON.
Encodage de base
Résultat :
{"name": "John Doe", "age": 30, "city": "New York", "hobbies": ["reading", "traveling", "photography"]}Affichage formaté avec indent et sort_keys
Par défaut, json.dumps() produit une chaîne compacte sur une seule ligne. Passez indent pour produire une sortie lisible par l'homme, et sort_keys=True pour trier les clés du dictionnaire par ordre alphabétique :
import json
person = {
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"]
}
print(json.dumps(person, indent=2, sort_keys=True))Résultat :
{
"age": 30,
"city": "New York",
"hobbies": [
"reading",
"traveling",
"photography"
],
"name": "John Doe"
}Utilisez indent=2 ou indent=4 lors de l'écriture de fichiers de configuration ou du débogage de réponses API — cela facilite la lecture des structures imbriquées.
Décoder des chaînes JSON en objets Python
json.loads() (load-string) analyse une chaîne JSON et retourne l'objet Python équivalent.
Décodage de base
Résultat :
{'name': 'John Doe', 'age': 30, 'city': 'New York', 'hobbies': ['reading', 'traveling', 'photography']}
<class 'dict'>
John DoeLa valeur décodée est un dictionnaire Python ordinaire, vous pouvez donc accéder à ses clés avec [] ou .get(), l'itérer avec for, etc.
Gérer le JSON malformé
Si l'entrée n'est pas du JSON valide, json.loads() lève json.JSONDecodeError. Interceptez toujours cette exception lorsque vous travaillez avec des données provenant de sources externes :
import json
raw = '{"name": "Alice", "age":}' # invalid — missing value
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
print(f"Invalid JSON: {e}")Résultat :
Invalid JSON: Expecting value: line 1 column 24 (char 23)Consultez le chapitre Python try/except pour un guide complet sur la gestion des exceptions.
Travailler avec du JSON imbriqué
Les objets JSON peuvent contenir d'autres objets et tableaux (arrays) à n'importe quelle profondeur. Accédez aux valeurs imbriquées en utilisant la notation [] chaînée :
Résultat :
John
travelingPour les structures profondément imbriquées, envisagez d'utiliser .get() avec une valeur par défaut pour éviter KeyError sur les clés manquantes :
city = person.get("address", {}).get("city", "unknown")Le chapitre sur les dictionnaires imbriqués couvre les patterns pour travailler avec des dicts Python profondément imbriqués.
Lire et écrire des fichiers JSON
json.dump() écrit dans un objet fichier, et json.load() lit depuis un fichier. Ce sont les équivalents fichier de dumps/loads.
Écrire du JSON dans un fichier
import json
data = {"name": "Alice", "scores": [95, 87, 92]}
with open("data.json", "w") as f:
json.dump(data, f, indent=2)Cela crée data.json avec un contenu formaté. L'utilisation de with open(...) garantit que le fichier est fermé automatiquement — consultez la gestion des fichiers Python pour plus de détails.
Lire du JSON depuis un fichier
import json
with open("data.json") as f:
data = json.load(f)
print(data)
print(data["scores"])Résultat (en supposant le fichier écrit ci-dessus) :
{'name': 'Alice', 'scores': [95, 87, 92]}
[95, 87, 92]Exemple complet d'aller-retour
import json
# Write
config = {"host": "localhost", "port": 5432, "debug": False}
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
# Read back
with open("config.json") as f:
loaded = json.load(f)
print(loaded["port"]) # 5432
print(type(loaded["port"])) # <class 'int'>Récupérer du JSON depuis une API web
Dans la plupart des projets, vous décoderez du JSON provenant d'une réponse HTTP. La bibliothèque populaire requests rend cela simple :
import requests
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
response.raise_for_status() # raises an error for 4xx/5xx responses
data = response.json() # equivalent to json.loads(response.text)
print(data["title"])
print(data["completed"])response.json() appelle json.loads() en interne. Appelez toujours raise_for_status() avant l'analyse afin qu'une requête échouée ne retourne pas silencieusement un corps d'erreur.
Sérialisation personnalisée avec default
Le module json ne peut pas encoder des objets Python arbitraires (comme datetime.date) par défaut. Passez un callable default ou une sous-classe personnalisée JSONEncoder pour les gérer :
import json
import datetime
class DateEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.date):
return obj.isoformat()
return super().default(obj)
event = {"name": "Conference", "date": datetime.date(2024, 1, 15)}
print(json.dumps(event, cls=DateEncoder))Résultat :
{"name": "Conference", "date": "2024-01-15"}L'objet date est converti en sa chaîne ISO 8601 avant la sérialisation.
Désérialisation personnalisée avec object_hook
object_hook est appelé pour chaque objet JSON (dict) lors de son décodage. Vous pouvez l'utiliser pour transformer les données à la volée — par exemple, convertir des valeurs string vers les bons types Python :
import json
def as_record(d):
"""Convert age field from string to int if present."""
if "age" in d:
d["age"] = int(d["age"])
return d
raw = '{"name": "Bob", "age": "25"}'
person = json.loads(raw, object_hook=as_record)
print(person)
print(type(person["age"])) # <class 'int'>Résultat :
{'name': 'Bob', 'age': 25}
<class 'int'>Référence rapide
| Fonction | Direction | Source/cible |
|---|---|---|
json.dumps(obj) | Python → JSON | retourne un str |
json.loads(s) | JSON → Python | lit depuis un str |
json.dump(obj, f) | Python → JSON | écrit dans un fichier |
json.load(f) | JSON → Python | lit depuis un fichier |
Paramètres optionnels clés :
indent=2— affichage formaté avec une indentation de 2 espacessort_keys=True— trier les clés du dictionnaire par ordre alphabétiquecls=MyEncoder— utiliser une sous-classeJSONEncoderpersonnaliséeobject_hook=fn— transformer chaque objet dict décodé