Aide-mémoire jq : 30 modèles JSON en ligne de commande
Vous canalisez kubectl get pods -o json dans less, et votre terminal se fige sur un mur de deux mégaoctets de JSON. Tout ce que vous voulez, c’est le nom de chaque pod en phase Running. jq le fait avec trois caractères de filtre — à condition de connaître le vocabulaire.
Ceci n’est pas une référence de syntaxe. Ce sont 30 modèles que vous allez vraiment taper, regroupés par tâche : accéder, filtrer, transformer, agréger, formater, puis coller ensemble avec des outils réels comme kubectl, aws et docker.
Quand utiliser jq, un formateur navigateur ou du code
jq n’est pas toujours la bonne réponse. Les trois choix honnêtes ressemblent à ceci :
| Situation | Meilleur outil | Pourquoi |
|---|---|---|
| Une réponse API, besoin de surlignage syntaxique et de numéros de ligne | JSON Formatter dans le navigateur | Diff visuel, zéro configuration, privé dans le navigateur |
| Pipeline shell, traitement de logs, script CI, serveur distant | jq | Composable, scriptable, sans dépendance GUI |
| Logique métier, tests unitaires, branchements complexes | Code (JS / Python) | Vrai débogueur, types, bibliothèques |
Choisissez jq quand la tâche vit dans un pipeline shell — tout le reste est probablement plus simple ailleurs.
Installation et premier pipeline
jq se livre comme un binaire unique sur chaque plateforme majeure :
# macOS
brew install jq
# Debian / Ubuntu
sudo apt install jq
# Windows (winget)
winget install jqlang.jq
Un premier pipeline, avec le filtre identité :
curl -s https://api.github.com/users/octocat | jq .
Le filtre . prend son entrée et l’émet telle quelle, joliment formatée. À lui seul, il remplace la plupart des moments « laisse-moi ouvrir ce JSON dans un éditeur ».
Cinq flags couvrent 90 % des usages réels :
| Flag | Rôle |
|---|---|
-r | Sortie brute — retire les guillemets autour des résultats de type chaîne |
-c | Compact — une valeur JSON par ligne (NDJSON) |
-s | Slurp — rassemble toutes les entrées dans un seul tableau |
-R | Entrée brute — lit les lignes comme chaînes au lieu de JSON |
-n | Entrée null — ne lit pas stdin, utilise null comme entrée |
Le modèle mental central : filtres et pipes
Un filtre prend une valeur JSON en entrée et produit zéro ou plusieurs valeurs JSON en sortie. Les filtres se composent avec un pipe |, qui envoie chaque sortie du filtre de gauche comme entrée au filtre de droite. C’est le même modèle mental que les pipes shell, sauf que ce sont des valeurs JSON qui circulent, pas des octets.
# . — identité
echo '{"name":"Alice"}' | jq '.'
# .key — accès à un champ
echo '{"name":"Alice"}' | jq '.name'
# .key.sub — chemin profond
echo '{"user":{"email":"a@x.com"}}' | jq '.user.email'
# .[] — itérer les éléments du tableau (produit plusieurs sorties)
echo '[{"id":1},{"id":2}]' | jq '.[] | .id'
# Composition par pipe : chaque sortie de .items[] alimente .name
echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq '.items[] | .name'
Toute la grammaire tient là-dedans. Les 30 modèles ci-dessous ne sont que des combinaisons de ces primitives.
30 modèles que vous utiliserez vraiment
Chaque modèle montre le JSON d’entrée, la commande et la sortie. Copiez n’importe lequel dans votre terminal.
Accès et extraction (modèles 1–5)
Modèle 1 — Accès sécurisé avec ?
Accéder à un champ qui pourrait ne pas exister, sans planter :
echo '{"name":"Alice"}' | jq '.address?.city?'
# Sortie : null
Le ? supprime les erreurs sur les clés manquantes. Sans lui, .address.city lèverait une erreur de type si .address est absent.
Modèle 2 — Accès par chemin profond
echo '{"user":{"profile":{"email":"a@x.com"}}}' | jq '.user.profile.email'
# Sortie : "a@x.com"
Modèle 3 — Découpage de tableau
echo '[10,20,30,40,50]' | jq '.[1:3]'
# Sortie : [20, 30]
echo '[10,20,30,40,50]' | jq '.[-1]'
# Sortie : 50
Les indices négatifs comptent depuis la fin. Les tranches utilisent des intervalles semi-ouverts, comme en Python.
Modèle 4 — Descente récursive pour trouver chaque clé correspondante
echo '{"a":{"name":"x"},"b":[{"name":"y"},{"id":1}]}' | jq '.. | .name? | select(. != null)'
# Sortie : "x"
# "y"
.. parcourt toute la valeur de l’arbre. Combiné à .name? et select, il extrait chaque champ name à n’importe quelle profondeur — inestimable pour explorer des schémas JSON inconnus.
Modèle 5 — Lister toutes les clés d’un objet
echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys'
# Sortie : ["apple", "mango", "zebra"]
echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys_unsorted'
# Sortie : ["zebra", "apple", "mango"]
keys trie par ordre alphabétique ; keys_unsorted préserve l’ordre d’insertion.
Filtrer (modèles 6–10)
Modèle 6 — Filtrer un tableau par condition
echo '[{"age":20},{"age":30},{"age":40}]' | jq 'map(select(.age > 25))'
# Sortie : [{"age":30},{"age":40}]
map(f) applique f à chaque élément ; select(cond) ne garde que les éléments où la condition est vraie.
Modèle 7 — Correspondance de préfixe de chaîne
echo '[{"name":"api-gateway"},{"name":"web-ui"},{"name":"api-auth"}]' \
| jq '.[] | select(.name | startswith("api"))'
# Sortie : {"name":"api-gateway"}
# {"name":"api-auth"}
Aussi utiles : endswith("..."), contains("..."), test("^regex$").
Modèle 8 — Conditions combinées
echo '[{"type":"A","count":5},{"type":"A","count":15},{"type":"B","count":20}]' \
| jq '.[] | select(.type == "A" and .count > 10)'
# Sortie : {"type":"A","count":15}
and, or, not se comportent comme attendu.
Modèle 9 — Supprimer des champs sensibles
echo '{"user":"alice","password":"s3cret","token":"abc"}' | jq 'del(.password, .token)'
# Sortie : {"user":"alice"}
del() accepte plusieurs chemins et ne panique pas si l’un manque.
Modèle 10 — Dédupliquer par champ
echo '[{"id":1,"v":"a"},{"id":2,"v":"b"},{"id":1,"v":"a2"}]' | jq 'unique_by(.id)'
# Sortie : [{"id":1,"v":"a"},{"id":2,"v":"b"}]
unique déduplique les valeurs entières ; unique_by(f) déduplique par le résultat d’un filtre.
Transformer (modèles 11–15)
Modèle 11 — Renommer des champs
echo '[{"first_name":"Alice","age":30}]' | jq 'map({name: .first_name, age})'
# Sortie : [{"name":"Alice","age":30}]
La syntaxe raccourcie {age} équivaut à {age: .age}.
Modèle 12 — Ajouter un champ calculé avec interpolation de chaîne
echo '[{"first":"Alice","last":"Chen"}]' \
| jq 'map(. + {fullName: "\(.first) \(.last)"})'
# Sortie : [{"first":"Alice","last":"Chen","fullName":"Alice Chen"}]
\(expr) évalue expr et interpole sa valeur dans la chaîne.
Modèle 13 — Aplatir des tableaux imbriqués
echo '[{"tags":["a","b"]},{"tags":["c"]}]' | jq '[.[] | .tags[]]'
# Sortie : ["a","b","c"]
echo '[[1,2],[3,[4,5]]]' | jq 'flatten'
# Sortie : [1,2,3,4,5]
flatten accepte une profondeur optionnelle : flatten(1) ne retire qu’un niveau.
Modèle 14 — Objet vers tableau et inverse
echo '{"a":1,"b":2}' | jq 'to_entries'
# Sortie : [{"key":"a","value":1},{"key":"b","value":2}]
echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# Sortie : {"a":1,"b":2}
Ce couple permet des transformations qui nécessitent d’itérer sur les clés d’un objet — ce que la syntaxe à points ne permet pas directement.
Modèle 15 — Fusion profonde de deux objets
echo '{"a":{"x":1},"b":2}' | jq '. * {a:{y:9}, c:3}'
# Sortie : {"a":{"x":1,"y":9},"b":2,"c":3}
L’opérateur * fait une fusion profonde. Pour une fusion plate, utilisez + (le côté droit l’emporte).
Agréger (modèles 16–20)
Modèle 16 — Longueur des tableaux, objets et chaînes
echo '[1,2,3,4]' | jq 'length' # 4
echo '{"a":1,"b":2}' | jq 'length' # 2
echo '"hello"' | jq 'length' # 5
Modèle 17 — Somme d’un champ
echo '[{"price":10},{"price":25},{"price":5}]' | jq '[.[].price] | add'
# Sortie : 40
add additionne les nombres, concatène les chaînes ou fusionne les tableaux — selon le type d’entrée.
Modèle 18 — Regrouper par champ
echo '[{"cat":"A","n":1},{"cat":"B","n":2},{"cat":"A","n":3}]' | jq 'group_by(.cat)'
# Sortie : [[{"cat":"A","n":1},{"cat":"A","n":3}],[{"cat":"B","n":2}]]
Chaque groupe devient un tableau interne. Combinez avec map pour agréger par groupe.
Modèle 19 — Trier par ordre décroissant
echo '[{"date":"2026-01-03"},{"date":"2026-01-01"},{"date":"2026-01-02"}]' \
| jq 'sort_by(.date) | reverse'
# Sortie : [{"date":"2026-01-03"},{"date":"2026-01-02"},{"date":"2026-01-01"}]
Les dates ISO 8601 se trient correctement comme chaînes. Pour d’autres formats, analysez d’abord — le guide des timestamps Unix couvre en détail epoch secondes, millisecondes et conversions de fuseau horaire.
Modèle 20 — Max ou min par champ
echo '[{"name":"a","rating":4.1},{"name":"b","rating":4.8},{"name":"c","rating":3.9}]' \
| jq 'max_by(.rating)'
# Sortie : {"name":"b","rating":4.8}
min_by, max_by renvoient un seul élément. Pour le top N, utilisez sort_by(.rating) | reverse | .[:N].
Formater la sortie (modèles 21–25)
Modèle 21 — Sortie CSV
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' \
| jq -r '.[] | [.name, .age] | @csv'
# Sortie : "Alice",30
# "Bob",25
@csv place des guillemets autour des chaînes et échappe les guillemets à l’intérieur. -r retire les guillemets JSON externes pour que le CSV soit directement redirigeable. Pour l’aller-retour complet entre CSV et JSON dans un pipeline, voir le guide de conversion CSV vers JSON.
Modèle 22 — Sortie TSV
echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' \
| jq -r '.[] | [.id, .name] | @tsv'
# Sortie : 1 Alice
# 2 Bob
La sortie tabulée se combine bien avec cut, awk et column -t.
Modèle 23 — Sortie de chaîne brute
echo '["alpha","beta"]' | jq -r '.[]'
# Sortie : alpha
# beta
Sans -r, chaque ligne aurait des guillemets autour. La sortie brute est celle que vous alimentez à xargs, while read ou une autre commande shell.
Modèle 24 — NDJSON / JSON Lines
echo '[{"a":1},{"a":2}]' | jq -c '.[]'
# Sortie : {"a":1}
# {"a":2}
Chaque ligne est une valeur JSON autonome — le format utilisé par Kafka, Elasticsearch et la plupart des loggeurs structurés. -c retire aussi tout espace interne.
Modèle 25 — Interpolation de chaîne pour sortie formatée
echo '[{"name":"server-1","cpu":0.73},{"name":"server-2","cpu":0.21}]' \
| jq -r '.[] | "\(.name) : \(.cpu * 100) % CPU"'
# Sortie : server-1 : 73 % CPU
# server-2 : 21 % CPU
Parfait pour les résumés et les lignes de log où le JSON brut serait du bruit.
DevOps sur le terrain (modèles 26–30)
Modèle 26 — kubectl : noms de chaque pod en cours d’exécution
kubectl get pods -o json \
| jq -r '.items[] | select(.status.phase=="Running") | .metadata.name'
Pipeline : itérer les pods, ne garder que Running, émettre le nom comme chaîne brute.
Modèle 27 — AWS EC2 : identifiants d’instance avec IP publique
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | [.InstanceId, .PublicIpAddress // "none"] | @tsv'
L’opérateur alternatif // fournit une valeur de repli quand le champ est null — évite un null littéral dans la colonne de sortie.
Modèle 28 — API GitHub : fusionner les résultats paginés
for p in 1 2 3; do
curl -s "https://api.github.com/orgs/myorg/repos?per_page=100&page=$p"
done | jq -s 'add | map(.name)'
-s rassemble toutes les réponses en un tableau de tableaux, add les concatène, puis map(.name) extrait les noms. Un schéma récurrent pour toute API paginée.
Modèle 29 — Filtrer des fichiers de logs structurés
cat app.log | jq -c 'select(.level=="error")'
Suppose que le fichier de logs est en NDJSON (un objet JSON par ligne). Combiné à tail -f pour du monitoring en direct :
tail -f app.log | jq -c 'select(.level=="error") | {ts: .timestamp, msg: .message}'
Modèle 30 — Docker : tous les noms d’images en cours d’usage
docker inspect $(docker ps -q) | jq -r '.[].Config.Image' | sort -u
Pratique pour vérifier rapidement quelles versions d’images tournent sur un hôte.
Erreurs courantes et leurs solutions
Tout utilisateur de jq tombe sur celles-ci. Connaître la solution d’avance fait gagner des heures.
Cannot iterate over null (null)
Le champ d’entrée que vous avez tenté d’itérer était null ou absent. Deux solutions :
# Option A : opérateur optionnel
echo '{}' | jq '.items[]?'
# Sortie : (rien, aucune erreur)
# Option B : opérateur alternatif avec valeur par défaut
echo '{}' | jq '(.items // [])[]'
# Sortie : (rien, aucune erreur)
Utilisez ? quand vous voulez sauter silencieusement. Utilisez // [] quand vous voulez forcer un tableau vide concret pour que les filtres suivants continuent à s’exécuter.
Cannot index array with "key"
Vous avez écrit .foo mais la valeur actuelle est un tableau. Ajoutez [] pour itérer :
# Faux
echo '{"users":[{"name":"Alice"}]}' | jq '.users.name'
# Erreur : Cannot index array with "name"
# Correct
echo '{"users":[{"name":"Alice"}]}' | jq '.users[].name'
# Sortie : "Alice"
Pièges de guillemets shell
Utilisez des apostrophes simples autour du programme jq entier, des guillemets doubles à l’intérieur pour les littéraux de chaîne :
# Fonctionne partout
jq '.users[] | select(.role == "admin")'
# Casse — les guillemets doubles sont d'abord interprétés par le shell
jq ".users[] | select(.role == \"admin\")"
Cas limite PowerShell Windows
PowerShell ne traite pas les apostrophes de la même manière. Préférez les guillemets doubles autour du programme en échappant les guillemets internes, ou utilisez une here-string :
jq "@'
.users[] | select(.role == \"admin\")
'@"
Pour tout ce qui est non trivial, enregistrez le filtre dans un fichier .jq et exécutez jq -f filter.jq.
Mauvais usage de -r
-r n’affecte que les résultats de type chaîne. Lui donner un objet produit un objet JSON normal :
echo '{"a":1}' | jq -r '.'
# Sortie : {"a":1} ← inchangé ; -r n'avait rien à désélectionner
Si vous voulez un champ spécifique sans guillemets, sélectionnez-le d’abord : jq -r '.a'.
jq refuse le JSON avec commentaires ou virgules finales
echo '{"a": 1, /* note */ "b": 2,}' | jq .
# parse error: Invalid numeric literal
jq suit strictement RFC 8259 JSON — pas de commentaires, pas de virgules finales, pas de clés sans guillemets. Si le fichier est JSON5 ou JSONC (courant pour la configuration), dépouillez ces extensions avant de pipe vers jq. Le guide de formatage JSON5 et JSONC explique quels parseurs les gèrent et comment convertir en JSON strict.
jq face aux alternatives : gron, fx, jj, yq
jq n’est pas la seule option, et parfois un autre outil va plus vite :
| Outil | Force | Quand le dégainer |
|---|---|---|
| gron | Aplatit le JSON en chemins grepables | Explorer des schémas inconnus — vous ne savez pas où est la clé |
| fx | Explorateur TUI interactif avec surlignage | Parcourir à la main de gros fichiers JSON |
| jj | Beaucoup plus rapide que jq, syntaxe limitée | Boucles chaudes traitant des millions d’enregistrements |
| yq | Même langage de filtre mais pour YAML | Manifestes Kubernetes et configuration CI |
| JSON Formatter navigateur | Surlignage syntaxique, messages d’erreur précis, zéro installation | Déboguer une réponse unique pendant le développement |
Pour le travail shell quotidien, jq gagne sur la composabilité. Pour une exploration ponctuelle, gron est souvent plus rapide. Pour du YAML, utilisez yq — ne tentez pas le canal yq-puis-jq.
Astuces pro pour l’usage quotidien
Quelques habitudes qui rendent jq naturel :
-
Gardez un
.jqrcdans$HOME. Déposez-y des fonctions utilitaires, et elles sont disponibles dans chaque invocation dejq:def running: select(.status.phase == "Running"); def table(f): [f] | @tsv; -
Utilisez jqplay.org pour les filtres complexes. Collez votre JSON à gauche, itérez le filtre à droite, expédiez la version qui marche dans votre script.
-
Construisez votre propre aide-mémoire depuis
history.history | grep 'jq ' | sort -u > ~/jq-patterns.txtcapture tous les modèles que vous avez réellement utilisés. -
Combinez avec le JSON Formatter du navigateur pour des schémas inconnus. Explorez d’abord la structure visuellement pour trouver le chemin nécessaire, puis écrivez la commande
jq. -
Surveiller des valeurs en direct :
watch -n 5 "curl -s api.example.com/health | jq '.uptime'"rafraîchit toutes les 5 secondes — un petit tableau de bord ops sans aucune dépendance.
FAQ
Qu’est-ce que jq et pourquoi les développeurs l’utilisent ?
jq est un processeur JSON en ligne de commande. Il extrait, filtre et transforme du JSON dans un pipeline shell sans script Python ou Node — le chemin le plus court entre des réponses API, des fichiers de logs ou une sortie kubectl et le champ voulu.
jq est-il disponible sous Windows ?
Oui. Installez via winget install jqlang.jq, Chocolatey choco install jq, ou téléchargez le binaire depuis jqlang.org. Les règles de guillemets de PowerShell diffèrent de bash — en cas de doute, enregistrez les filtres dans un fichier .jq et exécutez jq -f filter.jq.
En quoi jq diffère-t-il d’un formateur JSON navigateur ?
Un JSON Formatter navigateur est interactif — collez du JSON, visualisez le surlignage et les erreurs, copiez. jq est non interactif — décrivez la transformation une fois, exécutez-la dans un pipeline shell. Utilisez le navigateur pour déboguer une seule réponse ; utilisez jq pour automatiser sur des centaines d’entrées.
Pourquoi jq dit-il « Cannot iterate over null » ?
Vous avez tenté d’itérer (.[]) sur une valeur null — habituellement parce que le champ était absent de l’entrée. Corrigez avec l’opérateur optionnel .items[]? ou fournissez une valeur par défaut avec .items // [] | .[].
jq peut-il modifier les fichiers sur place ?
Pas directement — jq écrit sur stdout. Utilisez un fichier temporaire ou sponge de moreutils : jq '.version = "2.0"' config.json | sponge config.json. Sauvegardez toujours l’original d’abord ; un filtre mal écrit écrasera le fichier.
Comment utiliser jq avec des réponses curl ?
Redirigez curl -s dans jq. Le flag -s silence la barre de progression de curl pour que seul le corps JSON atteigne jq :
curl -s https://api.github.com/users/octocat | jq '.name, .blog'
Quelle est la différence entre le | de jq et le | du shell ?
Le pipe shell transmet des octets entre processus. Le pipe jq transmet des valeurs JSON entre filtres dans une seule invocation de jq. Une commande avec plusieurs pipes internes tourne dans un seul processus — moins cher qu’un chaînage jq | jq | jq.
jq peut-il gérer JSON Lines (NDJSON) ?
Oui, nativement. jq lit chaque ligne comme une valeur JSON indépendante quand elles sont séparées par des espaces. Utilisez -c pour émettre du NDJSON et -s pour collecter du NDJSON en un seul tableau.
Comment formater joliment du JSON sans filtrer ?
Utilisez le filtre identité : cat data.json | jq . ou jq . < data.json. Il analyse, valide et formate avec une indentation de deux espaces — aucun filtre requis.
Existe-t-il une alternative à jq avec une interface graphique ?
Oui. fx fournit une TUI interactive. Pour une interface graphique sans installation, le JSON Formatter basé navigateur couvre la plupart des besoins d’exploration et de validation. Les outils web comme jqplay.org offrent jq lui-même avec une prévisualisation en direct.
Quand utiliser jq plutôt qu’écrire un script Python ?
Choisissez jq quand la tâche est ponctuelle, tient dans un pipeline shell, et reste dans la sémantique filtrer/transformer/extraire. Passez à Python pour les tests unitaires, l’état complexe, les bibliothèques tierces, ou une logique qui déborderait d’un fichier .jq lisible.
Comment utiliser des expressions régulières dans jq ?
jq expose les regex via test("pattern"), match("pattern"), capture("pattern") et scan("pattern"), tous en syntaxe PCRE. Passez des flags en deuxième argument : test("abc"; "i") pour insensible à la casse. match renvoie offsets et captures ; scan émet chaque correspondance non chevauchante.
Comment préserver les caractères accentués (é, à, ç) dans la sortie de jq ?
jq émet de l’UTF-8 par défaut et conserve les caractères accentués tant que vous n’utilisez pas -a / --ascii-output. Si vous voyez \u00e9 au lieu de é, vérifiez que votre terminal est en UTF-8 (echo $LANG devrait afficher fr_FR.UTF-8 ou en_US.UTF-8) et évitez le flag -a.
À retenir
- Le modèle mental d’abord : un filtre entre, zéro ou plusieurs valeurs JSON sortent, on compose avec
|. Tout le reste est syntaxe. - Apprenez par tâche, pas par opérateur : les 30 modèles ci-dessus couvrent environ 95 % de l’usage quotidien de
jq. - Gérez null explicitement :
?pour un saut silencieux,// defaultpour un repli concret. La plupart des corrections deCannot iterate over nullpassent par l’un de ces deux outils. - Savoir quand
jqest le mauvais outil : les réponses uniques appartiennent à un JSON Formatter navigateur ; le YAML appartient àyq; la logique complexe appartient à du vrai code. - Associez-le à votre pile existante :
jqbrille à l’intérieur decurl,kubectl,aws,dockeret des pipelines de logs. Utilisez-le comme colle, pas comme couche logique.
Pour des flux JSON connexes, voir le guide de formatage JSON5 et JSONC pour les extensions de syntaxe des fichiers de configuration, et le guide de conversion CSV vers JSON pour les migrations de formats de données où jq s’insère dans le pipeline. Quand votre JSON contient des horodatages, le guide des timestamps Unix couvre les pièges que vous rencontrerez en transformant des champs de date.