jq — Interrogation et transformation JSON
Règle de lecture sélective
Commencez par :
references/senior-master-standard.mdreferences/usage-routing.mdreferences/quality-checklist.md
Ensuite, chargez uniquement les documents hérités, scripts, ressources ou exemples qui correspondent à la tâche réelle de l'utilisateur.
Présentation
jq est l'outil CLI standard pour interroger et remodeler le JSON. Cette compétence couvre une utilisation pratique et experte : filtrer des données profondément imbriquées, transformer des structures, agréger des valeurs et composer jq dans des pipelines shell. Chaque exemple est prêt à être copié-collé pour des workflows réels.
Quand utiliser cette compétence
- À utiliser lors de l'analyse de sorties JSON d'API, d'outils CLI (AWS, GitHub, kubectl, docker) ou de fichiers journaux
- À utiliser lors de la transformation de structures JSON (renommer des clés, aplatir des tableaux, regrouper des enregistrements)
- À utiliser lorsque l'utilisateur a besoin de
jqdans un script bash ou une ligne de commande unique - À utiliser pour expliquer ce que fait une expression
jqcomplexe
Comment ça fonctionne
jq prend une expression de filtre et l'applique à une entrée JSON. Les filtres se composent avec des tubes (|), et jq gère nativement les tableaux, objets, chaînes, nombres, booléens et null.
Sélection de base
# Extraire un champ
echo '{"name":"alice","age":30}' | jq '.name'
# "alice"
# Accès imbriqué
echo '{"user":{"email":"[email protected]"}}' | jq '.user.email'
# Index de tableau
echo '[10, 20, 30]' | jq '.[1]'
# 20
# Tranche de tableau
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3, 4]
# Tous les éléments d'un tableau
echo '[{"id":1},{"id":2}]' | jq '.[]'
Filtrage avec select
# Ne conserver que les éléments correspondants
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# Comparaison numérique
curl -s https://api.github.com/repos/owner/repo/issues \
| jq '[.[] | select(.comments > 5)]'
# Tester si un champ existe et n'est pas nul
jq '[.[] | select(.email != null)]'
# Combiner des conditions
jq '[.[] | select(.active == true and .score >= 80)]'
Mappage et transformation
# Extraire un champ de chaque élément du tableau
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' \
| jq '[.[] | .name]'
# ["alice", "bob"]
# Raccourci : map()
jq 'map(.name)'
# Construire un nouvel objet par élément
jq '[.[] | {user: .name, years: .age}]'
# Ajouter un champ calculé
jq '[.[] | . + {senior: (.age > 28)}]'
# Renommer des clés
jq '[.[] | {username: .name, email_address: .email}]'
Agrégation et réduction
# Somme de toutes les valeurs
echo '[1, 2, 3, 4, 5]' | jq 'add'
# 15
# Somme d'un champ dans des objets
jq '[.[].price] | add'
# Compter les éléments
jq 'length'
# Max / min
jq 'max_by(.score)'
jq 'min_by(.created_at)'
# reduce : accumulateur personnalisé
echo '[1,2,3,4,5]' | jq 'reduce .[] as $x (0; . + $x)'
# 15
# Grouper par champ
jq 'group_by(.department)'
# Compter par groupe
jq 'group_by(.status) | map({status: .[0].status, count: length})'
Interpolation de chaînes et formatage
# Interpolation de chaînes
jq -r '.[] | "\(.name) a \(.age) ans"'
# Formater en CSV (sans en-tête)
jq -r '.[] | [.name, .age, .email] | @csv'
# Formater en TSV
jq -r '.[] | [.name, .score] | @tsv'
# Encoder URL d'une valeur
jq -r '.query | @uri'
# Encoder Base64
jq -r '.data | @base64'
Travailler avec des clés et des chemins
# Lister toutes les clés de premier niveau
jq 'keys'
# Vérifier si une clé existe
jq 'has("email")'
# Supprimer une clé
jq 'del(.password)'
# Supprimer des clés imbriquées de chaque élément
jq '[.[] | del(.internal_id, .raw_payload)]'
# Descente récursive : trouver toutes les valeurs d'une clé n'importe où dans l'arbre
jq '.. | .id? // empty'
# Obtenir tous les chemins de feuilles
jq '[paths(scalars)]'
Conditionnelles et gestion d'erreurs
# if-then-else
jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
# Opérateur alternatif : utiliser une valeur de repli si nul ou faux
jq '.nickname // .name'
# try-catch : ignorer les erreurs au lieu de s'arrêter
jq '[.[] | try .nested.value catch null]'
# Supprimer la sortie nulle avec // empty
jq '.[] | .optional_field // empty'
Intégration pratique avec le shell
# Lire depuis un fichier
jq '.users' data.json
# Sortie compacte (sans espace blanc) pour redirection ultérieure
jq -c '.[]' records.json | while IFS= read -r record; do
echo "Traitement : $record"
done
# Passer une variable shell dans jq
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
# Passer un nombre
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# Lire plusieurs lignes JSON dans un tableau
jq -s '.' records.ndjson
# Plusieurs fichiers : tout lire dans un seul tableau
jq -s 'add' file1.json file2.json
# Pipeline null-safe à partir d'une commande
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# GitHub CLI : extraire les numéros de PR
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
# AWS CLI : lister les ID des instances en cours d'exécution
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# Docker : afficher les noms et images des conteneurs
docker inspect $(docker ps -q) | jq -r '.[] | "\(.Name)\t\(.Config.Image)"'
Modèles avancés
# Transposer un objet de tableaux en un tableau d'objets
# Entrée : {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# Aplatir un niveau
jq 'flatten(1)'
# Uniques par champ
jq 'unique_by(.email)'
# Trier, dédoublonner et ré-indexer
jq '[.[] | .name] | unique | sort'
# walk : appliquer une transformation à chaque nœud récursivement
jq 'walk(if type == "string" then ascii_downcase else . end)'
# env : lire les variables d'environnement dans jq
export API_KEY=secret
jq -n 'env.API_KEY'
Meilleures pratiques
- Utilisez toujours
-r(sortie brute) lorsque vous passez les résultats dejqà des variables shell ou à d'autres commandes pour supprimer les guillemets des chaînes JSON - Utilisez
--arg/--argjsonpour injecter des variables shell en toute sécurité — n'interpolez jamais directement des variables shell dans les chaînes de filtre - Préférez
map(f)à[.[] | f]pour la lisibilité - Utilisez
-c(compact) pour les pipelines JSON délimités par des sauts de ligne ; omettez-le pour le débogage lisible par l'homme - Testez les filtres de manière interactive avec
jq -net une entrée littérale avant de les intégrer dans des scripts - Utilisez
emptypour supprimer les éléments indésirables plutôt que de les filtrer versnull
Notes de sécurité
jqest en lecture seule par conception — il ne peut pas écrire de fichiers ni exécuter de commandes- Évitez d'intégrer directement des valeurs de champ JSON non fiables dans des commandes shell ; citez toujours ou utilisez
--arg
Pièges courants
-
Problème :
jqrenvoienullau lieu de la valeur attendue Solution : Vérifiez les fautes de frappe dans les noms de clés ; utilisezkeyspour inspecter les noms de champs réels. Rappelez-vous que JSON est sensible à la casse. -
Problème : Les nombres sont cités comme des chaînes dans la sortie Solution : Utilisez
--argjsonau lieu de--arglors de l'injection de valeurs numériques. -
Problème : Le filtre fonctionne dans le terminal mais échoue dans un script Solution : Assurez-vous que la chaîne de filtre utilise des guillemets simples dans le shell pour empêcher l'expansion des variables. Exemple :
jq '.field'pasjq ".field". -
Problème :
addrenvoienullsur un tableau vide Solution : Utilisezadd // 0ouadd // ""pour fournir une valeur par défaut de repli. -
Problème : Le streaming de fichiers volumineux est lent Solution : Utilisez
jq --streamou passez àjstream/gronpour les très gros fichiers.
Compétences connexes
@bash-pro— Envelopper les appels jq dans des scripts shell robustes@bash-linux— Modèles généraux de pipeline shell@github-automation— Utiliser jq avec la sortie JSON de GitHub CLI
Limitations
- Utilisez cette compétence uniquement lorsque la tâche correspond clairement au champ décrit ci-dessus.
- Ne traitez pas la sortie comme un substitut à une validation spécifique à l'environnement, à des tests ou à un examen par un expert.
- Arrêtez-vous et demandez des clarifications si les entrées requises, les autorisations, les limites de sécurité ou les critères de succès sont manquants.