La commande jq permet d'analyser (parser), valider, afficher et retravailler des objets JSON1). L'utilitaire s’exécute en ligne de commande (CLI).
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 }
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"
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" ]
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
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 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 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 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