jq est un outil en ligne de commande conçu pour lire, filtrer, transformer
et manipuler des données au format
JSON. Dans un monde où les
APIs et les fichiers de configuration s’appuient
massivement sur ce format, jq devient indispensable pour tout administrateur
système ou développeur DevOps.
Son principal avantage ? Permettre des requêtes complexes sur des structures de données imbriquées, directement depuis un terminal, sans avoir à écrire de script en Python ou en JavaScript.
L’API utilisée dans ce guide
Section intitulée « L’API utilisée dans ce guide »Pour illustrer chaque commande jq de manière concrète, nous allons utiliser l’API publique JSONPlaceholder. C’est une API gratuite qui simule les fonctionnalités d’un service REST, idéale pour s’exercer sans avoir à configurer un backend.
Pourquoi cette API ?
- Elle retourne des données JSON réalistes : utilisateurs, articles, commentaires, etc.
- Elle est accessible sans authentification.
- Les réponses sont structurées de manière cohérente, parfaites pour apprendre à manipuler des objets et tableaux JSON.
Nous nous appuierons notamment sur ces deux points d’entrée :
https://jsonplaceholder.typicode.com/users: pour manipuler une liste d’utilisateurs.https://jsonplaceholder.typicode.com/posts: pour travailler avec des publications et filtrer les contenus.
Toutes les requêtes seront faites avec
curl et traitées avec jq, directement
en ligne de commande. Ainsi, tu pourras reproduire chaque commande sur ton
propre terminal, sans installation complexe.
Syntaxe de base
Section intitulée « Syntaxe de base »jq s’utilise principalement de deux façons : en lisant un fichier JSON ou en traitant un flux de données en entrée standard (stdin). Ces deux méthodes sont interchangeables selon le contexte.
Lire un fichier JSON
Section intitulée « Lire un fichier JSON »La syntaxe classique consiste à passer un fichier JSON en argument :
jq '.' fichier.jsonIci, le filtre . signifie “affiche tout”. Cette commande affiche le contenu
JSON avec une indentation propre, ce qui facilite la lecture.
Lire depuis l’entrée standard (stdin)
Section intitulée « Lire depuis l’entrée standard (stdin) »jq peut également lire directement depuis un flux, comme celui produit par
une commande curl :
curl -s https://jsonplaceholder.typicode.com/users | jq '.'
[ { "id": 1, "name": "Leanne Graham", "username": "Bret", "email": "Sincere@april.biz", "address": { "street": "Kulas Light", "suite": "Apt. 556", "city": "Gwenborough", "zipcode": "92998-3874", "geo": { "lat": "-37.3159", "lng": "81.1496" } }, "phone": "1-770-736-8031 x56442", "website": "hildegard.org", "company": { "name": "Romaguera-Crona", "catchPhrase": "Multi-layered client-server neural-net", "bs": "harness real-time e-markets" } }, ...]Dans ce cas, jq reçoit les données JSON via le pipe |, les interprète
et les formate à l’écran.
Extraction de données spécifiques
Section intitulée « Extraction de données spécifiques »Avec jq, tu peux extraire précisément les éléments qui t’intéressent dans une structure JSON. Voici comment faire à partir de l’API JSONPlaceholder, qui renvoie une liste d’utilisateurs.
Extraire une clé simple
Section intitulée « Extraire une clé simple »Affichons tous les noms des utilisateurs :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[].name'"Leanne Graham""Ervin Howell""Clementine Bauch""Patricia Lebsack""Chelsey Dietrich""Mrs. Dennis Schulist""Kurtis Weissnat""Nicholas Runolfsdottir V""Glenna Reichert""Clementina DuBuque"Le filtre .[].name signifie : “dans chaque élément du tableau principal,
affiche la clé name”.
Extraire plusieurs clés
Section intitulée « Extraire plusieurs clés »Pour chaque utilisateur, on peut extraire plusieurs informations à la fois :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {id: .id, nom: .name, email: .email}'{ "id": 1, "nom": "Leanne Graham", "email": "Sincere@april.biz"}{ "id": 2, "nom": "Ervin Howell", "email": "Shanna@melissa.tv"}{ "id": 3, "nom": "Clementine Bauch", "email": "Nathan@yesenia.net"}{ "id": 4, "nom": "Patricia Lebsack", "email": "Julianne.OConner@kory.org"}{ "id": 5, "nom": "Chelsey Dietrich", "email": "Lucio_Hettinger@annie.ca"}{ "id": 6, "nom": "Mrs. Dennis Schulist", "email": "Karley_Dach@jasper.info"}{ "id": 7, "nom": "Kurtis Weissnat", "email": "Telly.Hoeger@billy.biz"}{ "id": 8, "nom": "Nicholas Runolfsdottir V", "email": "Sherwood@rosamond.me"}{ "id": 9, "nom": "Glenna Reichert", "email": "Chaim_McDermott@dana.io"}{ "id": 10, "nom": "Clementina DuBuque", "email": "Rey.Padberg@karina.biz"}Voici ce que fait en détail la commande :
-
curl -s https://jsonplaceholder.typicode.com/usersCette commande envoie une requête HTTP GET à l’API JSONPlaceholder. Le drapeau-ssignifie “silent”, donccurln’affiche pas la barre de progression. Le résultat est un tableau JSON contenant 10 utilisateurs. -
jq '.[]'Ce filtre dit à jq : “Parcours chaque élément du tableau”. Cela signifie que jq va traiter chaque utilisateur un par un. -
| {id: .id, nom: .name, email: .email}Pour chaque utilisateur, jq crée un nouvel objet JSON composé uniquement de trois clés :id→ la valeur du champ.id(identifiant de l’utilisateur)nom→ la valeur du champ.nameemail→ la valeur du champ.email
Ce type de transformation est parfait pour simplifier l’affichage, extraire des données ciblées, ou préparer une exportation vers un autre outil.
Extraire une clé imbriquée
Section intitulée « Extraire une clé imbriquée »Affichons le nom et la ville de chaque utilisateur :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {nom: .name, ville: .address.city}'{ "nom": "Leanne Graham", "ville": "Gwenborough"}{ "nom": "Ervin Howell", "ville": "Wisokyburgh"}{ "nom": "Clementine Bauch", "ville": "McKenziehaven"}{ "nom": "Patricia Lebsack", "ville": "South Elvis"}{ "nom": "Chelsey Dietrich", "ville": "Roscoeview"}{ "nom": "Mrs. Dennis Schulist", "ville": "South Christy"}{ "nom": "Kurtis Weissnat", "ville": "Howemouth"}{ "nom": "Nicholas Runolfsdottir V", "ville": "Aliyaview"}{ "nom": "Glenna Reichert", "ville": "Bartholomebury"}{ "nom": "Clementina DuBuque", "ville": "Lebsackbury"}.address.city permet d’accéder à une propriété imbriquée dans un objet
"address".
Extraire un élément par son index
Section intitulée « Extraire un élément par son index »Pour obtenir les données du 3e utilisateur :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[2]'
{ "id": 3, "name": "Clementine Bauch", "username": "Samantha", "email": "Nathan@yesenia.net", "address": { "street": "Douglas Extension", "suite": "Suite 847", "city": "McKenziehaven", "zipcode": "59590-4157", "geo": { "lat": "-68.6102", "lng": "-47.0653" } }, "phone": "1-463-123-4447", "website": "ramiro.info", "company": { "name": "Romaguera-Jacobson", "catchPhrase": "Face to face bifurcated interface", "bs": "e-enable strategic applications" }}Les tableaux JSON commencent à l’index 0. .[2] cible donc le 3e élément.
Accès à un champ d’un élément spécifique
Section intitulée « Accès à un champ d’un élément spécifique »Extraire uniquement l’email du 5e utilisateur :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[4].email'Tu peux combiner les index avec les noms de clés pour naviguer dans la structure.
Astuce pour les noms de champs avec des tirets
Section intitulée « Astuce pour les noms de champs avec des tirets »Si un champ contient un caractère spécial, utilise les guillemets doubles et
l’opérateur . :
jq '."nom-du-champ"' fichier.jsonMême si ce cas ne se produit pas dans JSONPlaceholder, il est bon à connaître pour d’autres API.
Filtres et transformations
Section intitulée « Filtres et transformations »Le point d’entrée https://jsonplaceholder.typicode.com/users retourne une
liste de 10 utilisateurs, chacun avec des champs comme id, name,
email, et un objet address contenant city, zipcode, etc. Voici comment
transformer ces données avec jq.
Sélectionner certains utilisateurs avec select
Section intitulée « Sélectionner certains utilisateurs avec select »Filtrons les utilisateurs vivant dans la ville de “McKenziehaven” :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | select(.address.city == "McKenziehaven")'Le filtre select(.address.city == "McKenziehaven") affiche uniquement les
utilisateurs correspondant à ce critère.
Supprimer un champ avec del
Section intitulée « Supprimer un champ avec del »Retirons les adresses complètes des utilisateurs :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | del(.address)'Cette commande supprime le champ address de chaque objet utilisateur.
Renommer et réorganiser les champs
Section intitulée « Renommer et réorganiser les champs »Construisons une vue simplifiée avec des noms de champs personnalisés :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {identifiant: .id, nom: .name, ville: .address.city}'Ici, on crée un nouvel objet avec des clés renommées et un sous-champ extrait.
Ajouter un champ statique
Section intitulée « Ajouter un champ statique »Ajoutons une clé statut à tous les utilisateurs :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | . + {statut: "actif"}'Chaque objet utilisateur contient maintenant une clé statut avec la valeur
"actif".
Compter le nombre d’utilisateurs
Section intitulée « Compter le nombre d’utilisateurs »Pour obtenir le total d’entrées dans la réponse JSON :
curl -s https://jsonplaceholder.typicode.com/users | jq 'length'Le filtre length compte les objets du tableau.
Extraire un tableau de valeurs avec map
Section intitulée « Extraire un tableau de valeurs avec map »Récupérons une liste des emails :
curl -s https://jsonplaceholder.typicode.com/users | jq 'map(.email)'Ce filtre renvoie un tableau contenant uniquement les adresses email des utilisateurs.
Utilisation avancée de jq
Section intitulée « Utilisation avancée de jq »Une fois les bases maîtrisées, jq permet d’aller beaucoup plus loin grâce à
des filtres avancés, des combinaisons logiques, et des fonctions intégrées.
Voici quelques usages puissants, toujours avec le point d’entrée
https://jsonplaceholder.typicode.com/users.
Combiner plusieurs conditions avec and / or
Section intitulée « Combiner plusieurs conditions avec and / or »Filtrons les utilisateurs dont l’ID est supérieur à 5 et vivant dans la ville de “Howemouth” :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | select(.id > 5 and .address.city == "Howemouth")'Avec and, jq évalue plusieurs conditions sur un même objet. On peut aussi
utiliser or :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | select(.id < 3 or .address.city == "Lebsackbury")'Appliquer une fonction à une chaîne ou un nombre
Section intitulée « Appliquer une fonction à une chaîne ou un nombre »Obtenir tous les noms en majuscules :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {nom_majuscule: (.name | ascii_upcase)}'Ici, ascii_upcase convertit la valeur de .name en majuscules.
Filtrer sur une valeur contenue (avec contains)
Section intitulée « Filtrer sur une valeur contenue (avec contains) »Trouver les utilisateurs dont le nom contient “Glen” :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | select(.name | contains("Glen"))'contains est sensible à la casse. Pour ignorer la casse, on peut combiner avec
ascii_downcase :
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | select((.name | ascii_downcase) | contains("glen"))'Trier les données (tri local)
Section intitulée « Trier les données (tri local) »On peut trier les utilisateurs par nom :
curl -s https://jsonplaceholder.typicode.com/users | jq 'sort_by(.name)[] | {id, nom: .name}'sort_by(.name) trie le tableau par ordre alphabétique selon .name.
Liste des Fonctions intégrées
Section intitulée « Liste des Fonctions intégrées »jq propose une riche collection de fonctions intégrées pour manipuler des données JSON en ligne de commande. Ces fonctions couvrent des opérations sur les chaînes, les tableaux, les objets, les nombres, les types, et bien plus encore. Voici un aperçu des principales catégories de fonctions disponibles :
Fonctions sur les chaînes de caractères
Section intitulée « Fonctions sur les chaînes de caractères »length: Renvoie la longueur d’une chaîne.ascii_upcase/ascii_downcase: Convertit une chaîne en majuscules ou minuscules.split/join: Divise une chaîne en tableau ou joint un tableau en chaîne.startswith/endswith: Vérifie si une chaîne commence ou se termine par une sous-chaîne donnée.contains: Vérifie si une chaîne contient une sous-chaîne spécifique.
Fonctions sur les tableaux
Section intitulée « Fonctions sur les tableaux »map: Applique une transformation à chaque élément d’un tableau.select: Filtre les éléments d’un tableau selon une condition.add: Additionne les éléments d’un tableau numérique.sort/sort_by: Trie les éléments d’un tableau.unique/unique_by: Supprime les doublons dans un tableau.reverse: Inverse l’ordre des éléments d’un tableau.
Fonctions sur les objets
Section intitulée « Fonctions sur les objets »keys: Renvoie les clés d’un objet.has: Vérifie la présence d’une clé dans un objet.del: Supprime une clé d’un objet.to_entries/from_entries: Convertit un objet en tableau de paires clé/valeur et inversement.with_entries: Transforme les paires clé/valeur d’un objet
Fonctions mathématiques
Section intitulée « Fonctions mathématiques »floor/ceil/round: Arrondit un nombre vers le bas, le haut ou à l’entier le plus proche.sqrt: Calcule la racine carrée d’un nombre.tonumber: Convertit une chaîne en nombre.
Fonctions de type et de conversion
Section intitulée « Fonctions de type et de conversion »type: Renvoie le type JSON d’une valeur (string,number,object, etc.).tostring: Convertit une valeur en chaîne de caractères.isfinite/isnan/isinfinite: Vérifie les propriétés d’un nombre.
Fonctions de parcours et de récursion
Section intitulée « Fonctions de parcours et de récursion »recurse: Parcourt récursivement une structure JSON.walk: Applique une fonction à chaque élément d’une structure JSON.paths/getpath/setpath: Travaille avec les chemins dans une structure JSON.
Fonctions de contrôle de flux
Section intitulée « Fonctions de contrôle de flux »if/then/else/end: Structure conditionnelle.try/catch: Gestion des erreurs.empty: Ne produit aucune sortie, utile pour filtrer des éléments.
Fonctions diverses
Section intitulée « Fonctions diverses »range: Génère une séquence de nombres.error: Génère une erreur personnalisée.input/inputs: Lit des entrées supplémentaires.
Pour une liste complète et détaillée des fonctions intégrées de jq, consulte la documentation officielle : https://jqlang.org/manual/
Voici alors des exemples concrets inédits de fonctions intégrées
avancées de jq, toujours à partir de l’endpoint
https://jsonplaceholder.typicode.com/users, et non couvertes précédemment
:
Quelques exemples avancés
Section intitulée « Quelques exemples avancés »curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {id_texte: (.id | tostring)}'→ Convertit le champ numérique id en texte, utile pour concaténations ou
formats spécifiques.
curl -s https://jsonplaceholder.typicode.com/users | jq '.[] | {nom: (.name | type), adresse: (.address | type)}'→ Affiche les types de données (string, object, etc.) pour des champs
donnés.
curl -s https://jsonplaceholder.typicode.com/users | jq '.[0] | with_entries(.key |= ascii_upcase)'→ Met en majuscules toutes les clés du premier utilisateur.
curl -s https://jsonplaceholder.typicode.com/users | jq '.[0] | to_entries | map(.key += "_mod") | from_entries'→ Renomme toutes les clés du premier utilisateur en ajoutant un suffixe _mod.
curl -s https://jsonplaceholder.typicode.com/users | jq '.[0] | recurse(.[]? | select(type == "object"))'→ Explore récursivement toutes les clés imbriquées du premier utilisateur.
curl -s https://jsonplaceholder.typicode.com/users | jq '.[0] | walk(if type == "string" then ascii_downcase else . end)'→ Met en minuscules toutes les chaînes de caractères du premier utilisateur, quelle que soit leur profondeur.
Conclusion
Section intitulée « Conclusion »À travers ce guide, tu as appris à manipuler les données JSON en ligne de commande avec jq, depuis les bases jusqu’aux transformations complexes. Grâce à cette maîtrise, tu peux maintenant intégrer jq dans tes scripts d’automatisation, que ce soit pour :
- Extraire des métriques de réponse API,
- Nettoyer des données JSON pour des dashboards ou du monitoring,
- Convertir des objets complexes en formats simplifiés pour des outils CLI ou des pipelines CI/CD.
jq est compact, rapide, sans dépendance, et surtout puissant : c’est un outil incontournable pour tout administrateur système, développeur ou DevOps travaillant avec des flux JSON.
Liens utiles
Section intitulée « Liens utiles »- Documentation officielle de jq
- jqlang : Utilise jq en ligne pour tester tes commandes.
FAQ - Questions Fréquemment Posées
Section intitulée « FAQ - Questions Fréquemment Posées »Définition
jq est un processeur JSON en ligne de commande permettant filtrage, transformation et manipulation de données JSON avec syntaxe déclarative.
| Caractéristique | Description |
|---|---|
| Type | Parser/transformateur JSON |
| Syntaxe | Langage filtres (pipes) |
| Entrée | JSON (fichier, stdin, API) |
| Sortie | JSON, texte, CSV |
| Opérations | Select, map, reduce, sort, group |
| Performance | Streaming (gros fichiers) |
Usages principaux
# 1. Pretty-print JSON
curl -s https://api.github.com/users/octocat | jq '.'
# 2. Extraire champ
echo '{"name":"Alice","age":30}' | jq '.name'
# "Alice"
# 3. Filtrer array
echo '[{"id":1},{"id":2}]' | jq '.[0]'
# {"id":1}
# 4. Transformer structure
jq '.users[] | {name: .username, email}' data.json
Cas DevOps
- APIs : Parser réponses Kubernetes, Terraform, AWS
- CI/CD : Extraire artifacts, manifests
- Configs : Manipuler package.json, manifests
- Logs : Filtrer JSON logs (CloudWatch, ELK)
- Secrets : Extraire tokens Vault, AWS
Contexte : Indispensable pour automatisation JSON, pipelines CLI.
Lecture basique
# Afficher tout (pretty-print)
jq '.' fichier.json
# Depuis stdin
cat fichier.json | jq '.'
# Depuis API
curl -s https://api.example.com/data | jq '.'
Filtre . (identité)
# JSON compact → indenté
echo '{"a":1,"b":2}' | jq '.'
# {
# "a": 1,
# "b": 2
# }
# Validation JSON
jq '.' data.json > /dev/null && echo "JSON valide"
Options lecture
| Option | Effet | Exemple |
|---|---|---|
-r |
Raw output (sans quotes) | jq -r '.name' data.json |
-c |
Compact (1 ligne) | jq -c '.' data.json |
-M |
Monochrome (pas couleurs) | jq -M '.' data.json |
-s |
Slurp (array global) | jq -s '.' *.json |
-e |
Exit code selon résultat | jq -e '.error' data.json |
Exemples pratiques
# Kubernetes pods (extrait)
kubectl get pods -o json | jq '.items[].metadata.name'
# Package.json version
jq -r '.version' package.json
# 1.2.3
# AWS EC2 instances IDs
aws ec2 describe-instances | jq -r '.Reservations[].Instances[].InstanceId'
Astuce : -r (raw) retire guillemets pour intégration scripts.
Pipeline curl + jq
# Pattern standard
curl -s URL | jq '.'
# Extraire champs
curl -s https://api.github.com/users/octocat | jq '.name, .bio'
# Avec authentification
curl -s -H "Authorization: Bearer TOKEN" \
https://api.example.com/data | jq '.results[]'
Exemples APIs courantes
# GitHub repos
curl -s https://api.github.com/users/microsoft/repos | \
jq '.[] | {name, stars: .stargazers_count}'
# JSONPlaceholder
curl -s https://jsonplaceholder.typicode.com/users | \
jq '.[].email'
# Kubernetes API
curl -sk -H "Authorization: Bearer $TOKEN" \
https://kubernetes:6443/api/v1/pods | \
jq '.items[] | select(.status.phase=="Running") | .metadata.name'
Filtrage et transformation
# Terraform Cloud workspaces
curl -s -H "Authorization: Bearer $TF_TOKEN" \
https://app.terraform.io/api/v2/organizations/my-org/workspaces | \
jq -r '.data[] | select(.attributes.locked == false) | .attributes.name'
# AWS API (via CLI)
aws ec2 describe-instances | \
jq -r '.Reservations[].Instances[] |
select(.State.Name=="running") |
"\(.InstanceId): \(.PrivateIpAddress)"'
Gestion erreurs
# Vérifier erreur API
RESPONSE=$(curl -s https://api.com/endpoint)
ERROR=$(echo "$RESPONSE" | jq -r '.error // empty')
if [ -n "$ERROR" ]; then
echo "API Error: $ERROR"
exit 1
fi
echo "$RESPONSE" | jq '.data'
Pattern DevOps : curl -sf URL | jq '.field' (fail si HTTP error).
Notation par points
# JSON exemple
echo '{
"user": {
"address": {
"city": "Paris",
"zip": "75001"
}
}
}' | jq '.user.address.city'
# "Paris"
# Sans quotes (-r)
jq -r '.user.address.city' data.json
# Paris
Navigation arrays
# Array index
echo '[{"name":"Alice"},{"name":"Bob"}]' | jq '.[0].name'
# "Alice"
# Tous éléments
echo '{"users":[{"id":1},{"id":2}]}' | jq '.users[].id'
# 1
# 2
# Range
jq '.items[2:5]' data.json # Index 2,3,4
Clés optionnelles
# Avec ? (pas d'erreur si absent)
jq '.user.email?' data.json
# Valeur par défaut
jq '.config.timeout // 30' data.json # 30 si absent
# Alternative operator
jq '.primary_email // .secondary_email' data.json
Cas complexes
# Kubernetes pod IP
kubectl get pod nginx -o json | \
jq -r '.status.podIP'
# AWS EC2 tags
aws ec2 describe-instances | \
jq -r '.Reservations[].Instances[].Tags[] |
select(.Key=="Name") | .Value'
# Terraform state
terraform show -json | \
jq -r '.values.root_module.resources[] |
select(.type=="aws_instance") |
.values.private_ip'
Gestion null
# Ignorer null
jq '.users[] | select(.email != null) | .email' data.json
# Remplacer null
jq '.items[] | .description // "N/A"' data.json
Fonction select()
# Filtrer par condition
jq '.users[] | select(.age > 18)' data.json
# Conditions multiples (AND)
jq '.[] | select(.active == true and .role == "admin")' data.json
# Conditions OR
jq '.[] | select(.status == "running" or .status == "pending")' data.json
Opérateurs comparaison
| Opérateur | Signification | Exemple |
|---|---|---|
== |
Égal | select(.id == 5) |
!= |
Différent | select(.status != "deleted") |
>, < |
Supérieur/inférieur | select(.age > 21) |
>=, <= |
Sup/inf ou égal | select(.score >= 80) |
contains |
Contient | select(.tags | contains(["prod"])) |
startswith |
Commence par | select(.name | startswith("app-")) |
Exemples pratiques
# Kubernetes pods actifs
kubectl get pods -o json | \
jq '.items[] | select(.status.phase=="Running") | .metadata.name'
# Docker containers en erreur
docker inspect $(docker ps -aq) | \
jq '.[] | select(.State.Status != "running") | .Name'
# GitLab MRs ouvertes
curl -s https://gitlab.com/api/v4/projects/123/merge_requests | \
jq '.[] | select(.state == "opened") | {title, author: .author.name}'
Filtres combinés
# AND logique
jq '.instances[] |
select(.type == "t3.micro" and .state == "running")' aws.json
# Regex
jq '.[] | select(.email | test("@company\\.com$"))' users.json
# Non-null
jq '.[] | select(.description) | .name' data.json
Pattern : select() retourne objet si true, sinon rien (filtre naturel).
Fonction del()
# Supprimer 1 champ
echo '{"name":"Alice","age":30,"temp":"x"}' | jq 'del(.temp)'
# {"name":"Alice","age":30}
# Supprimer plusieurs champs
jq 'del(.password, .secret, .token)' data.json
# Supprimer clé imbriquée
jq 'del(.user.metadata.internal)' data.json
Supprimer dans arrays
# Supprimer élément par index
jq 'del(.items[2])' data.json
# Supprimer selon condition
jq '.users |= map(del(.password))' data.json
# Supprimer array complet
jq 'del(.tags)' data.json
Exemples DevOps
# Nettoyer secrets Kubernetes
kubectl get secret mysecret -o json | \
jq 'del(.metadata.managedFields, .metadata.uid)' | \
kubectl apply -f -
# Package.json sans devDependencies
jq 'del(.devDependencies)' package.json > package-prod.json
# Terraform state sans metadata
terraform show -json | \
jq 'del(.lineage, .serial, .terraform_version)' > state-clean.json
Conservation inverse (garder)
# Garder seulement certains champs
jq '{name, email}' data.json # Nouveau objet
# Array : garder champs
jq '.users[] | {id, username}' data.json
Suppression conditionnelle
# Supprimer si null
jq 'del(.[] | select(. == null))' data.json
# Supprimer champs vides
jq 'del(..|select(. == ""))' data.json
Différence : del() modifie objet, {name,email} crée nouveau.
Construction nouvel objet
# Renommer via reconstruction
echo '{"old_name":"Alice","age":30}' | jq '{new_name: .old_name, age}'
# {"new_name":"Alice","age":30}
# Multiples renommages
jq '{id: .user_id, email: .user_email, active: .is_active}' data.json
Renommage avec opérateur
# with_entries (clés dynamiques)
jq '.users | with_entries(.key |= gsub("_"; "-"))' data.json
# user_name → user-name
# Renommer clé unique
jq '.user as $u | del(.user) | .profile = $u' data.json
Arrays d'objets
# Renommer dans array
jq '.items[] | {identifier: .id, label: .name}' data.json
# Map sur array
jq '.users | map({userId: .id, fullName: .name})' data.json
Cas pratiques
# Kubernetes labels (snake → camel)
kubectl get pods -o json | \
jq '.items[] |
{podName: .metadata.name,
namespace: .metadata.namespace,
hostIP: .status.hostIP}'
# AWS → format custom
aws ec2 describe-instances | \
jq '.Reservations[].Instances[] |
{instanceId: .InstanceId,
privateIP: .PrivateIpAddress,
state: .State.Name}'
# GitLab CI → simple format
curl -s https://gitlab.com/api/v4/projects/123/pipelines | \
jq '.[] | {pipelineId: .id, status, ref}'
Transformation complexe
# Aplatir structure imbriquée
jq '.user | {name, city: .address.city, country: .address.country}' data.json
# Concaténer champs
jq '{fullAddress: "\(.address.street), \(.address.city)"}' data.json
Pattern : {new: .old} crée objet avec clés renommées.
Opérateur + (merge)
# Ajouter champ fixe
echo '{"name":"Alice"}' | jq '. + {status: "active"}'
# {"name":"Alice","status":"active"}
# Multiples champs
jq '. + {env: "production", version: "1.0"}' data.json
Arrays d'objets
# Ajouter champ à tous éléments
jq '.users[] | . + {role: "user"}' data.json
# Map sur array
jq '.items | map(. + {processed: true})' data.json
Valeurs dynamiques
# Timestamp actuel
jq '. + {timestamp: now | todate}' data.json
# Variable shell
ENV="prod"
jq --arg env "$ENV" '. + {environment: $env}' data.json
# Calcul depuis champ existant
jq '. + {total: (.price * .quantity)}' data.json
Cas DevOps
# Kubernetes annotations
kubectl get deploy nginx -o json | \
jq '.metadata.annotations += {"deployed-by": "ci-cd",
"version": "v1.2.3"}' | \
kubectl apply -f -
# Docker labels
docker inspect nginx | \
jq '.[0].Config.Labels + {"app.version": "2.0",
"app.env": "staging"}'
# Package.json scripts
jq '.scripts += {"deploy": "npm run build && scp dist/* server:/"}' \
package.json > package.json.tmp && mv package.json.tmp package.json
Ajout conditionnel
# Ajouter si absent
jq '.config.timeout //= 30' data.json # 30 si null/absent
# Ajouter selon condition
jq 'if .env == "prod" then . + {ssl: true} else . end' data.json
Différence : + merge, |= update in-place.
Fonction sort_by()
# Tri par champ
echo '[{"name":"Bob","age":25},{"name":"Alice","age":30}]' | \
jq 'sort_by(.name)'
# Alice puis Bob (ordre alphabétique)
# Tri numérique
jq 'sort_by(.age)' users.json
# Tri descendant (reverse)
jq 'sort_by(.age) | reverse' users.json
Tri multi-critères
# Tri par 2 champs (priorité)
jq 'sort_by(.department, .name)' employees.json
# Tri avec transformation
jq 'sort_by(.name | ascii_downcase)' data.json # Ignore casse
# Tri par longueur
jq 'sort_by(.description | length)' data.json
Tri valeurs primitives
# Array simple
echo '[3,1,4,1,5]' | jq 'sort'
# [1,1,3,4,5]
# Strings
echo '["banana","apple","cherry"]' | jq 'sort'
# ["apple","banana","cherry"]
Cas DevOps
# Kubernetes pods par timestamp
kubectl get pods -o json | \
jq '.items | sort_by(.metadata.creationTimestamp) |
.[] | .metadata.name'
# Docker containers par utilisation CPU
docker stats --no-stream --format json | \
jq -s 'sort_by(.CPUPerc | rtrimstr("%") | tonumber) | reverse'
# AWS EC2 par coût (tag)
aws ec2 describe-instances | \
jq '.Reservations[].Instances |
sort_by(.Tags[] | select(.Key=="Cost") | .Value | tonumber)'
Tri avec null
# Null en premier
jq 'sort_by(.optional_field // "")' data.json
# Ignorer null
jq '[.[] | select(.field)] | sort_by(.field)' data.json
Group + Sort
# Grouper puis trier
jq 'group_by(.category) |
map({category: .[0].category,
items: sort_by(.name)})' data.json
Performance : sort_by() stable (ordre préservé si égalité).
Top 10 fonctions essentielles
| Fonction | Usage | Exemple |
|---|---|---|
| map() | Transformer array | map(.name) → liste noms |
| select() | Filtrer | select(.active == true) |
| sort_by() | Trier | sort_by(.age) |
| group_by() | Grouper | group_by(.category) |
| unique | Dédupliquer | unique_by(.id) |
| length | Compter | .items | length |
| keys | Lister clés | keys → array clés |
| has() | Tester présence | has("email") |
| contains() | Inclusion | contains({"status":"ok"}) |
| add | Somme/concat | [1,2,3] | add → 6 |
Manipulation strings
# Casse
jq '.name | ascii_upcase' data.json # MAJUSCULES
jq '.name | ascii_downcase' data.json # minuscules
# Split/join
jq '.path | split("/")' data.json # String → array
jq '.tags | join(", ")' data.json # Array → string
# Regex
jq '.email | test("@gmail.com$")' data.json # Boolean
jq '.text | gsub("old"; "new")' data.json # Remplacer
Fonctions aggregation
# Statistiques
jq '[.items[].price] | add' data.json # Somme
jq '[.items[].price] | max' data.json # Maximum
jq '[.items[].price] | min' data.json # Minimum
jq '[.items[].price] | add / length' data.json # Moyenne
# Groupe et compte
jq 'group_by(.status) | map({status: .[0].status, count: length})' data.json
Transformations avancées
# Aplatir (flatten)
echo '[[1,2],[3,4]]' | jq 'flatten'
# [1,2,3,4]
# Transposer
jq 'transpose' matrix.json
# Recursion
jq '.. | select(type == "string")' data.json # Tous strings
Cas DevOps
# Kubernetes : pods par node
kubectl get pods -o json | \
jq 'group_by(.spec.nodeName) |
map({node: .[0].spec.nodeName, count: length})'
# GitLab : MRs par auteur
curl -s https://gitlab.com/api/v4/projects/123/merge_requests | \
jq 'group_by(.author.username) |
map({author: .[0].author.username, mrs: map(.title)})'
# AWS : coût total tags
aws ce get-cost-and-usage ... | \
jq '[.ResultsByTime[].Groups[].Metrics.UnblendedCost.Amount |
tonumber] | add'
Cheat sheet : map() transforme, select() filtre, group_by() regroupe.