Table des matières

, , , ,

La commande jq

La commande jq permet d'analyser (parser), valider, afficher et retravailler des objets JSON1). 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

1)
JavaScript Object Notation