JSON vers Excel : quatre approches et où chacune perd la fidélité
L’essentiel : Les structures imbriquées, les champs incohérents et les tableaux de tableaux sont là où la conversion JSON vers tableur casse. Quatre approches classées par temps de résultat, chacune avec ses compromis.

L'essentiel : un tableau plat d'objets ou un objet enveloppant un tableau se convertit le plus vite via l'outil en ligne ; utilisez Power Query quand les données sont rafraîchies chaque semaine, pandas quand il y a beaucoup de champs à nettoyer, et un script Node seulement quand la conversion doit s'intégrer à un pipeline — mais décidez ce que signifie « une ligne » avant de toucher à des données imbriquées ou à des clés incohérentes.
La conversion elle-même n'est pas difficile ; ce qui est difficile, c'est de découvrir après coup que des nombres sont devenus du texte et que plusieurs niveaux d'imbrication se sont effondrés en un seul. Lisez la structure des données avant de choisir une méthode et vous vous épargnez une reprise.
1. D'abord, déterminez quel type de JSON vous avez
Ouvrez le fichier et regardez le niveau le plus externe :
| Structure | Forme | Difficulté de conversion |
|---|---|---|
| Tableau plat d'objets | [{"a":1,"b":2},{...}] |
La plus facile — une ligne par enregistrement |
| Objet enveloppant un tableau | {"data":[{...}],"total":100} |
Facile — prenez le niveau data |
| Objets imbriqués | {"user":{"name":"x"}} |
Moyenne — décidez entre aplatir ou joindre en chaîne |
| Tableaux de tableaux | {"tags":["a","b"]} |
Pénible — ne tient pas sur une ligne, nécessite un découpage de table |
| Clés incohérentes | Chaque enregistrement a des champs différents | Pénible — les colonnes finissent en grande partie vides |
Les deux premières se convertissent directement avec un taux de succès proche de 100 % ; pour les trois dernières, décidez d'abord de ce que signifie « une ligne », sinon la feuille obtenue est inutilisable.
2. Approche 1 : outil en ligne (1 minute)
Ouvrez JSON vers tableur, collez les données → choisissez le délimiteur et l'en-tête → exportez en CSV → ouvrez dans Excel. Adapté à quelques dizaines ou milliers de lignes de données bien structurées.
Trois choses à surveiller :
- Vous obtenez du CSV, pas du xlsx. Quand Excel ouvre un CSV, il devine l'encodage à partir de la locale du système, donc le texte chinois peut devenir du mojibake. Passer par « Données → À partir de texte/CSV » et sélectionner explicitement UTF-8 est plus fiable.
- Les identifiants commençant par
0perdent leurs zéros."007"est du texte dans le CSV, mais Excel le convertit automatiquement en nombre 7. Définissez cette colonne en texte lors de l'import, ou ajoutez un préfixe dans le JSON. - Les longs nombres deviennent de la notation scientifique. Les numéros d'identité nationale et les numéros de commande de plus de 15 chiffres perdent leur précision ; ces champs devraient déjà être des chaînes dans le JSON, et doivent rester en format texte après l'import.
3. Approche 2 : Power Query intégré à Excel (réutilisable)
Quand vos données sont rafraîchies chaque semaine, utilisez Power Query intégré à Excel : configurez une fois, puis cliquez simplement sur « Actualiser » :
- « Données » → « Obtenir des données » → « À partir d'un fichier » → « À partir de JSON » ;
- Après avoir choisi le fichier, vous arrivez dans l'éditeur Power Query, où vous voyez des structures
List/Record; - Cliquez sur l'icône d'expansion à droite d'un en-tête de colonne pour développer les champs imbriqués niveau par niveau ;
- Une fois les noms de colonnes et les types corrects, « Fermer et charger ».
L'avantage est que l'imbrication peut être développée en plusieurs colonnes couche par couche, et les types assignés manuellement ; le prix est que la première configuration exige de comprendre la différence entre List et Record — List est un tableau, Record est un objet, et ils s'étendent dans des directions différentes.
4. Approche 3 : Python + pandas (beaucoup de champs, besoin de nettoyage)
import pandas as pd
# Object wrapping an array: first reach the list level
rows = pd.read_json('data.json')['data']
# Expand nested fields into multiple columns
frame = pd.json_normalize(rows, sep='_')
frame.to_excel('out.xlsx', index=False)
Le paramètre clé de json_normalize est sep, qui détermine le style de nommage des colonnes après expansion des champs imbriqués ; user_name est plus facile à utiliser dans Excel que user.name. Les tableaux de tableaux (comme tags) nécessitent une étape explode supplémentaire :
frame = frame.explode('tags')
Cette étape découpe une ligne en plusieurs, la seule façon de préserver une relation un-à-plusieurs — au prix de la duplication des champs restants.
5. Approche 4 : un script Node (quand il faut s'intégrer à un pipeline)
import { readFileSync, writeFileSync } from 'node:fs';
const rows = JSON.parse(readFileSync('data.json', 'utf8'));
const headers = [...new Set(rows.flatMap((row) => Object.keys(row)))];
const escapeCell = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
const lines = [
headers.join(','),
...rows.map((row) => headers.map((key) => escapeCell(row[key])).join(',')),
];
writeFileSync('out.csv', '\uFEFF' + lines.join('\n'), 'utf8');
Deux détails à ne pas sauter : écrivez \uFEFF (un BOM) au début pour qu'Excel reconnaisse l'UTF-8, et échappez les guillemets doubles à l'intérieur des cellules en "", sinon les colonnes se décalent.
6. Trois choses que la conversion perd toujours
| Élément perdu | Symptôme | Remède |
|---|---|---|
| Information de type | Nombres et booléens deviennent du texte ou TRUE/FALSE |
Définir les types de colonnes manuellement après l'import, ou les spécifier dans Power Query |
| Niveaux d'imbrication | Les champs profonds s'effondrent en [object Object] |
Utiliser json_normalize ou développer niveau par niveau — jamais String(obj) |
| Relations un-à-plusieurs | Les tableaux sont fourrés dans une seule cellule | Découper les lignes avec explode, ou construire une table liée séparée |
De plus, null et « champ absent » se ressemblent dans une feuille (les deux sont des cellules vides) mais signifient des choses différentes dans le domaine métier. Quand il faut les distinguer, convertissez explicitement null en la chaîne "null" dans le JSON, ou ajoutez une colonne marqueur _has_field.
7. Vérifier après coup : ne regardez pas seulement la première ligne
Après la conversion, vérifiez par sondage au moins trois choses :
- Nombre d'enregistrements : le nombre de lignes CSV doit être égal à la longueur du tableau + 1 (l'en-tête) ; une ligne manquante signifie généralement que le retour à la ligne final a été avalé ;
- La colonne au taux de null le plus élevé : beaucoup de cellules vides indiquent des noms de clés incohérents — revenez vérifier si le JSON original utilise deux orthographes (
userIdetuser_id) ; - La ligne la plus longue : les tableaux imbriqués y atterrissent généralement ; confirmez que rien n'a été tronqué.
Quand il faut l'opération inverse (Excel/CSV vers JSON), utilisez CSV vers JSON, et rappelez-vous que l'en-tête est traité comme les noms de clés — changer l'en-tête revient à changer les noms de champs.
FAQ
Comment choisir entre l'outil en ligne, Power Query et pandas ?
Utilisez l'outil en ligne pour quelques dizaines ou milliers de lignes de données bien structurées que vous convertissez une fois. Utilisez Power Query quand les données sont rafraîchies chaque semaine, car il se configure une fois et se rafraîchit en un clic. Utilisez pandas avec json_normalize quand il y a beaucoup de champs à nettoyer, et un script Node quand la conversion doit s'intégrer à un pipeline.
Pourquoi le texte chinois devient-il du mojibake dans un CSV ?
L'export est du CSV, pas du xlsx, et Excel devine l'encodage à partir de la locale du système, donc de l'UTF-8 sans BOM s'affiche en mojibake. Écrivez un BOM \uFEFF au début du fichier, ou ouvrez-le via « Données → À partir de texte/CSV » et sélectionnez explicitement UTF-8.
Les objets imbriqués doivent-ils être aplatis ou découpés en lignes supplémentaires ?
Aplatissez-les niveau par niveau plutôt que de les coller en chaînes : Power Query développe les champs imbriqués en colonnes, et json_normalize avec sep fait de même dans pandas. Les tableaux de tableaux nécessitent une étape explode supplémentaire qui découpe une ligne en plusieurs. Passer un objet profond à String(obj) ne donne que [object Object].