Convertir rapidement des données JSON en CSV est un besoin récurrent pour analyser dans Excel ou Google Sheets, charger dans un datawarehouse ou partager un rapport simple. Avec jq, vous pouvez produire un CSV propre en une seule commande, sans écrire de script.
Dans cet article :
- Les primitives jq utiles pour le CSV (
@csv,@tsv,-r, sélection des champs) - Générer un CSV depuis un tableau d’objets JSON (avec ou sans en-tête)
- Gérer les champs imbriqués, les tableaux, les valeurs nulles et les types
- Traiter du JSON Lines (NDJSON) et de gros volumes
- Éviter les pièges fréquents (ordre des colonnes, guillemets, séparateurs)
Pré-requis : jq installé. Si vous débutez, voir Comment manipuler du JSON en ligne de commande avec jq.
Données d’exemple
Fichier users.json :
[
{"id": 1, "name": "Alice", "active": true, "tags": ["admin", "ops"], "score": 42.5, "created_at": "2025-09-01T12:00:00Z"},
{"id": 2, "name": "Bob", "active": false, "tags": ["dev"], "score": 12.1, "created_at": "2025-08-29T10:30:00Z"},
{"id": 3, "name": "Chloé", "active": true, "tags": ["dev", "ops"], "score": 31.7, "created_at": "2025-09-05T08:45:00Z"}
]
CSV le plus simple avec colonnes explicites
La méthode la plus robuste est d’énumérer explicitement les colonnes et leur ordre.
jq -r '.[] | [.id, .name, .active, .score] | @csv' users.json
Sortie :
1,"Alice",true,42.5
2,"Bob",false,12.1
3,"Chloé",true,31.7
Explications :
.[]parcourt chaque objet du tableau.[.id, .name, .active, .score]construit un tableau de champs, dans l’ordre voulu.@csvsérialise en CSV correct (échappement des guillemets).-r(raw) sort une chaîne brute sans guillemets JSON autour de la ligne.
Avantage : contrôle total de l’ordre et du sous-ensemble de colonnes.
Ajouter une ligne d’en-tête
Deux approches :
En-tête statique (facile) :
{
printf 'id,name,active,score\n';
jq -r '.[] | [.id, .name, .active, .score] | @csv' users.json;
} > users.csv
En-tête dynamique à partir des clés du premier objet :
jq -r '(
.[0] | keys_unsorted
) as $keys
| $keys,
(.[] | [ .[ $keys[] ] ])
| @csv' users.json
Note :
keys_unsortedlit les clés telles qu’elles apparaissent (pas triées). Selon vos données, l’ordre peut varier. Pour un ordre stable, préférez une liste explicite de colonnes.
Champs imbriqués et tableaux
Extraire une propriété imbriquée (avec valeur optionnelle) :
jq -r '.[] | [.id, .name, (.profile.city // ""), .score] | @csv' users.json
Convertir un tableau en chaîne séparée par ; :
jq -r '.[] | [.id, .name, (.tags | join(";")), .score] | @csv' users.json
Formater et convertir les types explicitement :
jq -r '.[] | [(.id|tostring), .name, (.active|tostring), (.score // 0)] | @csv' users.json
Filtrer, trier, sélectionner des colonnes
Uniquement les utilisateurs actifs, triés par score décroissant, colonnes réduites :
jq -r '.
| map(select(.active))
| sort_by(.score) | reverse
| .[] | [.id, .name, .score]
| @csv' users.json
Renommer des colonnes via l’en-tête statique :
{
printf 'user_id,full_name,score\n';
jq -r '.[] | [.id, .name, .score] | @csv' users.json;
} > users.csv
JSON Lines (NDJSON)
Si vous avez un fichier NDJSON (users.jsonl) avec un objet JSON par ligne :
{"id":1,"name":"Alice","active":true,"score":42.5}
{"id":2,"name":"Bob","active":false,"score":12.1}
{"id":3,"name":"Chloé","active":true,"score":31.7}
Deux patterns :
Avec en-tête statique :
{
printf 'id,name,active,score\n';
jq -r '[.id, .name, .active, .score] | @csv' users.jsonl;
} > users.csv
En-tête dynamique (déduit de la première ligne) :
jq -Rns ' # -R: lire brut, -n: pas d entree par defaut, -s: slurp
def fromjsonl: split("\n") | map(select(length>0) | fromjson);
(fromjsonl) as $rows
| ($rows[0] | keys_unsorted) as $keys
| $keys,
($rows[] | [ .[ $keys[] ] ])
| @csv' users.jsonl
Pour de très gros fichiers NDJSON, préférez l’en-tête statique et un traitement ligne à ligne (sans charger tout en mémoire).
TSV plutôt que CSV (quand c’est pertinent)
Le TSV est pratique quand vos valeurs contiennent souvent des virgules. Il s’aligne bien en terminal.
jq -r '.[] | [.id, .name, .active, .score] | @tsv' users.json > users.tsv
Aperçu lisible en colonne (Linux/macOS) :
column -t -s $'\t' users.tsv
Sous Windows PowerShell, utilisez
Format-Tableou importez le TSV dans Excel.
Gérer NULL, valeurs manquantes et formats
Valeurs manquantes vers chaîne vide :
jq -r '.[] | [.id, (.email // ""), (.score // 0)] | @csv' users.json
Forcer un formatage (ex: arrondir à 2 décimales) :
jq -r '.[] | [.id, .name, ( (.score // 0) | tonumber | (.*100|round/100) )] | @csv' users.json
Dates ISO vers date seule :
jq -r '.[] | [.id, (.created_at | split("T")[0])] | @csv' users.json
Gros volumes : streamer sans tout charger
Tableau massif : évitez map(...) si possible et parcourez en flux :
jq -r '.[] | [.id, .name, .score] | @csv' huge.json > out.csv
NDJSON massif : traitez ligne à ligne, en-tête statique :
{
printf 'id,name,score\n';
jq -r '[.id, .name, .score] | @csv' huge.jsonl;
} > out.csv
Astuce : ajoutez
pv(Linux/macOS) dans le pipeline pour suivre la progression :jq ... | pv > out.csv.
Options jq à retenir pour manipuler des CSV
-rraw-output : indispensable pour obtenir des lignes sans guillemets JSON externes@csv/@tsv: sérialisation sûre des valeurs (échappement, quoting)keys_unsorted: récupérer les noms de colonnes depuis un objet//(coalescence) : définir une valeur par défaut pour NULL ou absenttostring/tonumber: conversions explicites
Pièges et bonnes pratiques
- Ne faites pas confiance à l’ordre de
keyssi vos objets ont des clés différentes. Définissez vos colonnes explicitement pour des exports stables. - Utilisez toujours
-ravec@csvou@tsvpour éviter les guillemets JSON autour des lignes. - Si vos valeurs contiennent des virgules, sauts de ligne ou guillemets, laissez jq gérer l’échappement via
@csvplutôt que de concaténer des chaînes vous-même. - Préférez
@tsvquand vous regardez le résultat en terminal, convertissez en CSV plus tard si nécessaire. - Pour des datasets énormes, évitez
-s/--slurpet les agrégations inutiles. Streamez avec.[].
Conclusion
Avec quelques filtres bien choisis, jq devient un excellent exporteur CSV : rapide, fiable, scriptable. Définissez vos colonnes, pensez à -r et @csv, gérez les cas particuliers (NULL, champs imbriqués), et vous avez tout ce qu’il faut pour automatiser vos exports.