jq One-Liners Filtrer et transformer du JSON depuis la ligne de commande sans écrire un script
Sept recettes pratiques de jq pour les développeurs backend et les DevOps — couvrant select, map, to_entries, del, group_by et la réorganisation réelle d'API. L'entrée et la sortie sont affichées pour chaque modèle.
Vous regardez une réponse API minifiée dans votre terminal. Vous devez extraire 3 champs, filtrer les valeurs nulles et pipeler le résultat vers un autre outil. Écrire un script en Python pour cela demande 20 lignes et 2 minutes que vous n'avez pas. jq Cela se fait en une seule commande — si vous connaissez les modèles.
Sept recettes ci-dessous. Chaque une couvre un modèle que vous rencontrerez fréquemment lors du travail avec des réponses API ou des fichiers de journaux. L'entrée, la commande et la sortie sont présentées pour chaque recette.
Installation
brew install jq # macOS
apt-get install jq # Ubuntu/Debian
apk add jq # Alpine (Docker images)
Recette 1 : Extraire un champ de chaque objet dans un tableau
L'opération la plus courante que vous ferez avec jq: extraire un champ de chaque élément dans un tableau JSON.
Entrée (users.json)
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"},
{"id": 2, "name": "Bob", "email": "bob@example.com", "role": "user"},
{"id": 3, "name": "Carol", "email": "carol@example.com", "role": "user"}
]
jq '.[].name' users.json
# → "Alice"
# "Bob"
# "Carol" (newline-separated stream)
.[] itére sur chaque élément du tableau; .name extraire le champ. Le résultat est un flux — utile pour pipeler vers d'autres commandes. Si vous avez besoin d'un tableau JSON complet :
jq 'map(.name)' users.json
# → ["Alice", "Bob", "Carol"]
map(.name) est un raccourci pour [.[] | .name] — applique l'expression à chaque élément et enveloppe les résultats dans un tableau. Vous utiliserez map() beaucoup.
Recette 2 : Filtrer avec select
Conserver uniquement les objets qui correspondent à une condition ; éliminer les autres.
jq 'map(select(.role == "admin"))' users.json
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"}
]
select(expr) transmet l'élément uniquement si l'expression est vraie — tout le reste disparaît. Envelopper dans map() garantit que le résultat reste un tableau. Plus d'exemples :
# Numeric comparison
jq 'map(select(.score > 80))' results.json
# Not-null check
jq 'map(select(.error != null))' events.json
# String contains (requires test)
jq 'map(select(.message | test("timeout")))' logs.json
Recette 3 : Redessiner les objets avec map
Sélectionner uniquement les champs dont vous avez besoin et les renommer éventuellement dans la même étape.
jq 'map({name: .name, role: .role})' users.json
[
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"},
{"name": "Carol", "role": "user"}
]
Vous construisez un nouvel objet littéral pour chaque élément. Pour renommer une clé, modifiez le côté gauche de la colonne :
jq 'map({username: .name, access_level: .role})' users.json
Une abréviation qui économise des touches : {name} . Les pipes lisent de haut en bas dans l'ordre des opérations, ce qui explique pourquoi l'Elixir idiomatique place chaque {name: .name}. Si vous voulez un champ tel quel, vous n'avez pas besoin d'écrire la clé deux fois :
jq 'map({id, name, role})' users.json
Recette 4 : Renommer les clés avec to_entries et from_entries
map est utile lorsque vous savez quels clés existent. Lorsque vous devez transformer les clés elles-mêmes — ajouter un préfixe, modifier les conventions de nommage ou renommer selon une correspondance — to_entries est le modèle approprié.
Entrée (config.json)
{"api_url": "https://api.example.com", "timeout": 30, "retry_count": 3}
# Add cfg_ prefix to every key
jq 'to_entries | map(.key = "cfg_" + .key) | from_entries' config.json
{"cfg_api_url": "https://api.example.com", "cfg_timeout": 30, "cfg_retry_count": 3}
to_entries transforme {"k": "v"} dans [{"key": "k", "value": "v"}]. Après avoir modifié les entrées dans le tableau résultant, from_entries reconstitue l'objet. Pour renommer une clé spécifique sans toucher les autres :
jq 'to_entries | map(if .key == "api_url" then .key = "endpoint" else . end) | from_entries' config.json
Recette 5 : Supprimer des champs avec del
L'inverse de la redessinage : garder tout et supprimer quelques champs spécifiques. L'usage principal est de supprimer des données sensibles avant le journalisation ou avant de transmettre un payload à un service tiers.
jq 'map(del(.email))' users.json
[
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"},
{"id": 3, "name": "Carol", "role": "user"}
]
Supprimer plusieurs champs en une fois, ou des chemins imbriqués :
# Multiple top-level fields at once
jq 'del(.password, .token, .refresh_token)' user.json
# Nested path
jq 'del(.user.internal_id)' response.json
# All fields named "debug" at any depth (recursive descent)
jq 'del(.. | .debug? // empty)' response.json
Recette 6 : Filtrer, redessiner et trier en une seule étape
Le véritable avantage est de chaîner ces primitives. Voici un modèle qui apparaît constamment lors du travail avec des réponses API paginées : descendre dans un tableau imbriqué, le filtrer, redessiner les objets et trier le résultat.
Entrée (repos.json)
{
"total_count": 3,
"items": [
{"id": 1, "name": "repo-alpha", "stargazers_count": 142, "language": "Go", "private": false},
{"id": 2, "name": "repo-beta", "stargazers_count": 89, "language": "Python", "private": true},
{"id": 3, "name": "repo-gamma", "stargazers_count": 310, "language": "Go", "private": false}
]
}
jq '.items
| map(select(.private == false and .language == "Go"))
| sort_by(-.stargazers_count)
| map({name, stars: .stargazers_count})' repos.json
[
{"name": "repo-gamma", "stars": 310},
{"name": "repo-alpha", "stars": 142}
]
La chaîne de traitement :
.items— descendre dans le tableau imbriquémap(select(...))— filtrer en une seule étape;andchaîne des conditionssort_by(-.stargazers_count)— inverser la valeur pour un tri descendant;sort_by(.field)seule donne un tri croissantmap({name, stars: .stargazers_count})— redessinage final;{name}est un raccourci pour{name: .name}
Recette 7 : Compter les niveaux de journal avec group_by
Analyse de fréquence sur une sortie structurée de journal — sans base de données, sans gymnastique awk.
Entrée (logs.json)
[
{"level": "error", "msg": "connection timeout", "service": "auth"},
{"level": "info", "msg": "request received", "service": "api"},
{"level": "error", "msg": "null pointer exception", "service": "worker"},
{"level": "warn", "msg": "slow query detected", "service": "db"},
{"level": "error", "msg": "rate limit exceeded", "service": "api"}
]
jq 'group_by(.level) | map({level: .[0].level, count: length}) | sort_by(-.count)' logs.json
[
{"level": "error", "count": 3},
{"level": "info", "count": 1},
{"level": "warn", "count": 1}
]
group_by(.level) retourne un tableau de tableaux — chaque sous-tableau contient tous les entrées qui partagent la même valeur de niveau. .[0].level extrait le nom du niveau à partir du premier élément du groupe; length compte le nombre d'entrées dans le groupe.
Ajouter une analyse par service dans la même requête :
jq 'group_by(.level) | map({
level: .[0].level,
count: length,
services: map(.service) | unique
})' logs.json
Référence Rapide
Les modèles ci-dessus sous forme de tableau pour quand vous avez besoin d'un rappel rapide :
| Ce que vous souhaitez | Expression jq |
|---|---|
| Tous les valeurs d'un champ | map(.field) |
| Filtrer les éléments correspondants | map(select(.field == "val")) |
| Redessiner chaque objet | map({newKey: .oldKey}) |
| Renommer toutes les clés | to_entries | map(.key = ...) | from_entries |
| Supprimer des champs | map(del(.field1, .field2)) |
| Trier par ordre croissant | sort_by(.field) |
| Trier par ordre décroissant | sort_by(-.field) |
| Compter par groupe | group_by(.field) | map({key: .[0].field, count: length}) |
| Obtenir tous les noms de clés d'un objet | keys |
| Compter les éléments dans un tableau | length |
| Valeurs uniques d'un champ | map(.field) | unique |
Avant de commencer : Maîtriser le bloc
Les réponses API reviennent souvent minifiées ou profondément imbriquées. Si vous n'êtes pas sûr du chemin nécessaire, collez le JSON dans l' Formateur JSON — il affiche le JSON de manière lisible avec des nœuds pliables afin que vous puissiez identifier le chemin avant d'écrire l' jq expression. Après avoir appliqué une transformation, l' Comparaison JSON outil est utile pour vérifier la différence avant/après lorsque vous redessinez ou supprimez des champs et que vous souhaitez confirmer que rien de inattendu n'a changé.
Ces sept modèles couvrent la majorité des opérations de manipulation de JSON que vous effectuerez à la ligne de commande. Le vrai pouvoir réside dans la chaîne de ces primitives — une fois que vous pouvez filtrer, redessiner et trier, vous pouvez traiter la plupart des réponses API sans toucher un fichier de script.
Installez nos extensions
Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide
恵 Le Tableau de Bord Est Arrivé !
Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !
Outils essentiels
Tout voir Nouveautés
Tout voirMise à jour: Notre dernier outil a été ajouté le 8 juin 2026
