Skip to content
Retour au blog
Tutoriels

Aide-mémoire jq : 30 modèles JSON en ligne de commande

Maîtrisez jq avec 30 modèles éprouvés pour filtrer, transformer et extraire du JSON en ligne de commande — kubectl, AWS CLI et logs inclus.

12 min de lecture

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 :

SituationMeilleur outilPourquoi
Une réponse API, besoin de surlignage syntaxique et de numéros de ligneJSON Formatter dans le navigateurDiff visuel, zéro configuration, privé dans le navigateur
Pipeline shell, traitement de logs, script CI, serveur distantjqComposable, scriptable, sans dépendance GUI
Logique métier, tests unitaires, branchements complexesCode (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 :

FlagRôle
-rSortie brute — retire les guillemets autour des résultats de type chaîne
-cCompact — une valeur JSON par ligne (NDJSON)
-sSlurp — rassemble toutes les entrées dans un seul tableau
-REntrée brute — lit les lignes comme chaînes au lieu de JSON
-nEntré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 :

OutilForceQuand le dégainer
gronAplatit le JSON en chemins grepablesExplorer des schémas inconnus — vous ne savez pas où est la clé
fxExplorateur TUI interactif avec surlignageParcourir à la main de gros fichiers JSON
jjBeaucoup plus rapide que jq, syntaxe limitéeBoucles chaudes traitant des millions d’enregistrements
yqMême langage de filtre mais pour YAMLManifestes Kubernetes et configuration CI
JSON Formatter navigateurSurlignage syntaxique, messages d’erreur précis, zéro installationDé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 :

  1. Gardez un .jqrc dans $HOME. Déposez-y des fonctions utilitaires, et elles sont disponibles dans chaque invocation de jq :

    def running: select(.status.phase == "Running");
    def table(f): [f] | @tsv;
  2. 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.

  3. Construisez votre propre aide-mémoire depuis history. history | grep 'jq ' | sort -u > ~/jq-patterns.txt capture tous les modèles que vous avez réellement utilisés.

  4. 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.

  5. 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

  1. Le modèle mental d’abord : un filtre entre, zéro ou plusieurs valeurs JSON sortent, on compose avec |. Tout le reste est syntaxe.
  2. Apprenez par tâche, pas par opérateur : les 30 modèles ci-dessus couvrent environ 95 % de l’usage quotidien de jq.
  3. Gérez null explicitement : ? pour un saut silencieux, // default pour un repli concret. La plupart des corrections de Cannot iterate over null passent par l’un de ces deux outils.
  4. Savoir quand jq est le mauvais outil : les réponses uniques appartiennent à un JSON Formatter navigateur ; le YAML appartient à yq ; la logique complexe appartient à du vrai code.
  5. Associez-le à votre pile existante : jq brille à l’intérieur de curl, kubectl, aws, docker et 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.

Articles connexes

Voir tous les articles