Le jeu de données utilisé par Liora est un tableau JSON contenant des objets. Cette distinction est essentielle : [] sert à parcourir les éléments d’un tableau, tandis qu’un nom de champ comme .name permet d’accéder à une propriété d’un objet.
8.1.2 Tableau et objet JSON
jq reçoit du JSON en entrée et produit du JSON ou des valeurs extraites en sortie. Il est particulièrement adapté aux sorties d’API et aux outils d’administration qui renvoient des données structurées.
8.1.1 jq travaille sur des données JSON
8.1 Comprendre ce que jq manipule
8.2 Comprendre les filtres jq
8.2.1 Le point . : identité
cat people.json | jq .
Le filtre . reçoit l’objet d’entrée et le restitue. Il permet ici d’afficher proprement le JSON.
8.2.2 Parcourir un tableau avec []
Comme le document principal est un tableau, .[] permet d’en parcourir les éléments. Un champ peut ensuite être sélectionné, par exemple .name ou .birth_year.
cat people.json | jq '.[] | .birth_year'
8.2.3 Sélectionner une tranche
Le slicing permet de prendre une partie du tableau. Pour les cinq premiers éléments :
cat people.json | jq '.[0:5]'
8.2.4 Appliquer plusieurs filtres avec la virgule
cat people.json | jq '.[].name, .[].height'
La virgule applique plusieurs filtres à la même entrée : ici tous les noms, puis toutes les tailles.
8.2.5 Enchaîner les traitements avec le pipe
Comme dans Bash, le pipe transmet la sortie d’une étape à la suivante :
cat people.json | jq '.[] | .birth_year'
|, hors des quotes, est le pipe du shell entre cat et jq. Le second, à l’intérieur de l’expression jq, enchaîne deux filtres jq.8.2.6 Filtrer avec select()
select(condition) conserve uniquement les valeurs pour lesquelles la condition est vraie. Sur un tableau, on commence généralement par .[] afin d’envoyer chaque objet vers select().
Considérons le fichier utilisateurs.json :
[
{ "nom": "Axel", "age": 42, "actif": true },
{ "nom": "Claire", "age": 42, "actif": true },
{ "nom": "Lina", "age": 17, "actif": false }
]
Conserver les personnes majeures :
jq '.[] | select(.age >= 18)' utilisateurs.json
Conserver les personnes majeures et actives :
jq '.[] | select(.age >= 18 and .actif == true)' utilisateurs.json
Filtrer, puis extraire uniquement le nom sans guillemets JSON :
jq -r '.[] | select(.age >= 18) | .nom' utilisateurs.json
Reconstituer un tableau JSON contenant uniquement les résultats :
jq '[.[] | select(.age >= 18)]' utilisateurs.json
| Élément | Rôle |
|---|---|
.[] | Parcourt les objets du tableau. |
| | Transmet chaque résultat au filtre suivant. |
select(condition) | Ne conserve que les objets qui respectent la condition. |
.nom | Extrait ensuite la propriété nom. |
-r | Affiche les chaînes sans guillemets JSON. |
[ ... ] | Regroupe les résultats dans un nouveau tableau JSON. |
.[] | select(.actif == true) | .nom signifie « parcourir les utilisateurs, garder les actifs, puis afficher leur nom ».8.3 Construire de nouveaux résultats
8.3.1 Construire un tableau
Les crochets permettent de créer un nouveau tableau à partir des champs sélectionnés :
cat people.json | jq '.[] | [.name, .birth_year, .mass, .height]'
8.3.2 Construire un objet
Les accolades construisent un nouvel objet JSON :
cat people.json | jq '.[] | {name, height, films: .films[]}'
Un champ du premier niveau peut être repris directement avec son nom. Lorsqu’on veut construire une clé avec une expression différente, on écrit nouvelle_cle: expression.
8.3.3 Construire un document plus complexe
Cet exemple combine plusieurs mécanismes sur les dix premiers objets :
cat people.json | jq '.[:10] | .[] | {name, birth_year, mass, species: .species[], details: [.homeworld, .vehicles, .starships[]]}'
On combine ici slicing, parcours du tableau, construction d’objet et construction d’un tableau imbriqué.
8.4 Utiliser les opérateurs
8.4.1 Addition : +
Le comportement dépend du type des valeurs :
| Type | Effet de + |
|---|---|
| Nombres | Addition arithmétique. |
| Tableaux | Concaténation des tableaux. |
| Chaînes | Concaténation des chaînes. |
| Objets | Fusion des objets ; en cas de clé identique, la valeur de droite est conservée. |
jq '.[0].id + .[1].id' people.json
jq '.[0].species + .[1].species' people.json
jq '.[0].name + .[1].name' people.json
jq '.[] | {name, birth_year, mass} + {name, height}' people.json
8.4.2 Soustraction : -
Elle permet une soustraction numérique et peut aussi retirer des valeurs d’un tableau :
jq '.[0].films - ["http://swapi.co/api/films/6/", "http://swapi.co/api/films/7/"]' people.json
8.4.3 Multiplication : *
Elle multiplie des nombres ; appliquée entre une chaîne et un nombre, elle répète la chaîne :
jq '.[10].id * 15' people.json
jq '.[0].name * 3' people.json
8.4.4 Division : /
Outre la division numérique, / peut découper une chaîne selon un séparateur :
jq '.[0].name / "e"' people.json
Luke Skywalker devient alors un tableau contenant les morceaux séparés par la lettre e.
8.5 Regrouper et compter avec group_by et length
8.5.1 Regrouper les objets
cat people.json | jq 'group_by(.eye_color)'
group_by(.eye_color) crée plusieurs tableaux, un par valeur de eye_color.
8.5.2 Compter les éléments de chaque groupe
cat people.json | jq 'group_by(.eye_color)[] | {eye_color: .[0].eye_color, count: length}'
length renvoie ici le nombre d’objets du groupe. .[0].eye_color récupère la couleur sur un seul élément représentatif du groupe ; utiliser .[].eye_color produirait au contraire un résultat pour chaque personnage du groupe.
8.6 Le chemin logique avec jq
| Besoin | Écriture jq |
|---|---|
| Afficher l’entrée | . |
| Parcourir un tableau | .[] |
| Lire un champ | .name |
| Prendre une tranche | .[0:5] |
| Enchaîner des filtres | | |
| Filtrer selon une condition | select(condition) |
| Appliquer plusieurs filtres | , |
| Construire un tableau | [...] |
| Construire un objet | {...} |
| Regrouper | group_by(...) |
| Compter | length |
jq permet d’en extraire précisément une valeur ou de transformer la sortie avant de la transmettre à une autre étape d’un script ou d’un pipeline. Le cours souligne également son intérêt dans les traitements ETL.