{{tag>dev js json jq cli}}
====== La commande jq ======
La commande **jq** permet d'analyser (parser), valider, afficher et retravailler des objets **JSON**((**J**ava**S**cript **O**bject **N**otation)). L'utilitaire s’exécute en ligne de commande (CLI).
===== Mise en forme des objets JSON =====
Les objets JSON sont conçus pour l'échange d'informations en programmes. Ils ne sont pas aisément lisibles pour un lecteur humain:
# Ici la position de la station ISS est retournée par l'API sous forme de données formatée en JSON
curl -s http://api.open-notify.org/iss-now.json
{"iss_position": {"longitude": "-152.6537", "latitude": "-51.4075"}, "message": "success", "timestamp": 1639219539}
La commande **jq** introduit alinéas, retours à la ligne et coloration syntaxique pour faciliter la lisibilité et l'analyse des objets JSON:
# enregistre l'objet JSON dans un fichier
curl -s http://api.open-notify.org/iss-now.json > iss-postion.json
# mise en forme de l'ojet JSON
cat iss-position.json | jq
{
"iss_position": {
"longitude": "-99.6042",
"latitude": "-39.8896"
},
"message": "success",
"timestamp": 1639220152
}
===== Filtrer les attributs =====
**jq** permet de définir des filtres pour sélectionner les attributs à afficher:
# sélectionner seulement l'attribut timestamp de l'objet
cat iss-postion.json | jq .timestamp
1639220152
# Ici on récupère le timestamp et on le reformate via la commande date:
TS=$(cat iss-postion.json | jq .timestamp)
date --date="@$TS"
sam. 11 déc. 2021 11:55:52 CET
On peut définir un filtre sélectionnant plusieurs attributs:
cat iss-postion.json | jq ".iss_position.longitude, .iss_position.latitude"
"-99.6042"
"-39.8896"
# syntaxe équivalente: jq filtre fichier
jq ".iss_position.longitude, .iss_position.latitude" iss-postion.json
"-99.6042"
"-39.8896"
===== Les tableaux =====
Pour l'exemple on utilise encore l'API de la NASA. Ici on récupère la liste des astronautes présent dans les différents vaisseaux en orbite:
curl -s http://api.open-notify.org/astros.json > equipages.json
L'objet JSON possède un attribut people de type tableau:
# Sélectionner tous les éléments du tableau
jq ".people[]" equipages.json
# Sélectionner un élément via son index
jq ".people[4]" equipages.json
# Sélectionner plusieurs éléments par tranche (slice) ici les éléments 2 et 3
jq ".people[2:4]" equipages.json
**jq** permet également de définir un nouvel objet de type tableau à partir des éléments filtrés:
# On affiche l'objet initial:
jq . iss-postion.json
{
"iss_position": {
"longitude": "-99.6042",
"latitude": "-39.8896"
},
"message": "success",
"timestamp": 1639220152
}
# Créer un tableau de 3 éléments à partir de l'objet en entrée
jq "[.timestamp, .iss_position.latitude, .iss_position.longitude]" iss-postion.json
[
1639220152,
"-39.8896",
"-99.6042"
]
===== Combiner les filtres =====
Il est possible de combiner des filtres via les pipes ''|'':
# chaque élément du tableau contient deux paires dont les clés sont "craft" et "name"
jq ".people[0]" equipages.json
{
"craft": "ISS",
"name": "Mark Vande Hei"
}
# Ici on combine les filtres pour ne sélectionner que la clé "name":
jq ".people[0] | .name" equipages.json
"Mark Vande Hei"
Pour les objets complexes on peut ainsi combiner les filtres pour sélectionner et travailler les éléments souhaités dans des tableaux:
# On récupère la valeur de la clé "name" des 10 derniers éléments d'un tableau dans le fichier strike.json
jq ".[-10:] | .[] | .name" strikes.json
# On récupère les valeurs des clés "name" et "mass" des élements 450 à 454
jq ".[450:455] | .[] | .name, .mass" strikes.json
===== Usage des fonctions =====
==== La fonction delete ====
On peut retirer un attribut via la commande delete:
# Objet initial
jq . iss-postion.json
{
"iss_position": {
"longitude": "-99.6042",
"latitude": "-39.8896"
},
"message": "success",
"timestamp": 1639220152
}
# appel de la fonction delete produit une sortie sans la clé "message"
jq "del(.message)" iss-postion.json
{
"iss_position": {
"longitude": "-99.6042",
"latitude": "-39.8896"
},
"timestamp": 1639220152
}
==== La fonction length ====
La fonction length retourne la longueur des chaines, objets ou tableaux:
# détermine la taille du tableau .people
jq ".people | length" equipages.json
13
# on affiche le 13ième élément
jq ".people[12]" equipages.json
{
"craft": "ISS",
"name": "Yozo Hirano"
}
# L'élément contient 2 paires: craft et name de type chaines de caractères
# on affiche la taille du 13ième élément, puis la taille des valeurs de chaque clé
jq ".people[12] | length" equipages.json
2
jq ".people[12] | .[] | length" equipages.json
3
11
# équivalent
jq ".people[12] | .craft | length" equipages.json
3
jq ".people[12] | .name | length" equipages.json
11
==== La fonction keys ====
La fonction keys permet d'obtenir un tableau d'éléments listant les clés d'un objet en entrée:
jq ".people[12] | keys" equipages.json
[
"craft",
"name"
]
==== La fontion has() ====
La fonction has() permet de déterminer si un objet contient une clé particulière:
jq '.people[12] | has("firstname")' equipages.json
false
jq '.people[12] | has("name")' equipages.json
true
===== Références =====
* https://www.howtogeek.com/529219/how-to-parse-json-files-on-the-linux-command-line-with-jq/
* https://stedolan.github.io/jq/manual/