jq est le processeur JSON en ligne de commande que chaque administrateur Linux et ingénieur DevOps devrait avoir dans sa boîte à outils. Que vous travailliez avec des API REST, analysiez la sortie de Kubernetes, traitiez l’état Terraform ou extrayiez des données de fichiers journaux, jq vous permet de découper, filtrer et transformer du JSON directement depuis le terminal — sans avoir besoin d’un script Python.

Ce guide couvre tout, de l’extraction de champs basique aux transformations avancées, avec des exemples concrets que vous utiliserez quotidiennement.

Prérequis

  • Un système Linux (n’importe quelle distribution)
  • Familiarité de base avec les pipes shell et les outils en ligne de commande
  • Des données JSON avec lesquelles travailler (nous utiliserons des exemples tout au long du guide)

Installer jq

Sur Debian/Ubuntu :

sudo apt update && sudo apt install -y jq

Sur RHEL/Fedora/AlmaLinux :

sudo dnf install -y jq

Sur Alpine :

sudo apk add jq

Sur macOS :

brew install jq

Vérification :

jq --version

jq vs Autres Outils de Traitement JSON

OutilIdéal PourInconvénients
jqTransformations CLI rapides, pipes shellLa logique complexe devient verbeuse
Python jsonTraitement multi-étapes, logique complexeNécessite l’environnement Python, plus de code
yqTraitement YAML (syntaxe type jq)Installation séparée, spécifique YAML
fxExploration interactive de JSONNon scriptable
gronRendre JSON greppableUnidirectionnel (aplatissement uniquement)

jq l’emporte lorsque vous avez besoin de transformations rapides et scriptables dans un pipeline sans aucune dépendance au-delà du binaire.

jq Basique : Extraction de Données

Le Filtre Identité

L’opération jq la plus simple embellit l’affichage du JSON :

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.'
{
  "name": "nginx",
  "version": "1.25.3",
  "status": "running"
}

Extraction de Champs

Utilisez la notation par points pour extraire des valeurs spécifiques :

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.name'
"nginx"

Pour obtenir la chaîne brute sans guillemets, ajoutez -r :

echo '{"name":"nginx","version":"1.25.3"}' | jq -r '.name'
nginx

Le flag -r est essentiel pour les scripts. Sans lui, jq produit des chaînes encodées JSON (avec guillemets), ce qui casse les assignations de variables et les comparaisons dans bash.

Objets Imbriqués

echo '{"server":{"host":"10.0.0.1","port":8080}}' | jq '.server.port'
8080

Accès aux Tableaux

echo '["nginx","apache","caddy"]' | jq '.[0]'
"nginx"

Obtenir tous les éléments :

echo '["nginx","apache","caddy"]' | jq '.[]'
"nginx"
"apache"
"caddy"

Travailler avec de Vraies Réponses d’API

Voici un scénario réaliste : interroger une API REST et extraire ce dont vous avez besoin.

# Obtenir les infos utilisateur GitHub
curl -s https://api.github.com/users/torvalds | jq '{login, name, public_repos, followers}'
{
  "login": "torvalds",
  "name": "Linus Torvalds",
  "public_repos": 7,
  "followers": 223000
}

Extraction depuis des Tableaux d’Objets

La plupart des API retournent des tableaux. Voici comment travailler avec eux :

# Simuler une réponse d'API
cat << 'EOF' | jq '.servers[] | {name, status}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running"
}
{
  "name": "web-02",
  "status": "stopped"
}
{
  "name": "db-01",
  "status": "running"
}

Filtrer des Données JSON avec jq

La Fonction select()

Filtrer les tableaux pour ne garder que les éléments correspondants :

cat << 'EOF' | jq '.servers[] | select(.status == "running")'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running",
  "cpu": 45
}
{
  "name": "db-01",
  "status": "running",
  "cpu": 78
}

Comparaisons Numériques

# Serveurs avec utilisation CPU supérieure à 50%
cat servers.json | jq '.servers[] | select(.cpu > 50) | .name'

Combiner des Conditions

# Serveurs en cours d'exécution avec CPU élevé
cat servers.json | jq '.servers[] | select(.status == "running" and .cpu > 50)'

Correspondance de Chaînes

# Serveurs dont le nom contient "web"
cat servers.json | jq '.servers[] | select(.name | contains("web"))'

Pour la correspondance regex :

# Noms correspondant à un motif
cat servers.json | jq '.servers[] | select(.name | test("web-[0-9]+"))'

Transformer du JSON avec jq

Construire de Nouveaux Objets

Construire de nouvelles structures JSON à partir de données existantes :

cat << 'EOF' | jq '.servers[] | {hostname: .name, healthy: (.status == "running"), load: (.cpu / 100)}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "hostname": "web-01",
  "healthy": true,
  "load": 0.45
}
{
  "hostname": "db-01",
  "healthy": true,
  "load": 0.78
}

map() pour les Transformations de Tableaux

Transformer chaque élément d’un tableau :

echo '[1,2,3,4,5]' | jq 'map(. * 2)'
[2, 4, 6, 8, 10]

Exemple pratique — extraire uniquement les noms dans un tableau :

cat servers.json | jq '[.servers[].name]'
["web-01", "web-02", "db-01"]

Tri et Regroupement

# Trier par CPU décroissant
cat servers.json | jq '.servers | sort_by(.cpu) | reverse'

# Regrouper par statut
cat servers.json | jq '.servers | group_by(.status)'

Agrégations

# Compter les serveurs
cat servers.json | jq '.servers | length'

# CPU moyen
cat servers.json | jq '.servers | map(.cpu) | add / length'

# CPU maximum
cat servers.json | jq '.servers | max_by(.cpu) | .name'

jq dans les Scripts Shell

Stocker des Résultats dans des Variables

#!/bin/bash
response=$(curl -s https://api.github.com/users/torvalds)

name=$(echo "$response" | jq -r '.name')
repos=$(echo "$response" | jq -r '.public_repos')

echo "User: $name has $repos public repos"

Attention : Utilisez toujours des guillemets autour de la variable dans echo "$response". Les variables non quotées perdent les espaces blancs et cassent l’analyse JSON.

Itérer sur des Tableaux JSON

#!/bin/bash
# Traiter chaque serveur depuis l'API
curl -s https://api.example.com/servers | jq -r '.[] | .name' | while read -r server; do
    echo "Checking $server..."
    ping -c 1 -W 2 "$server" > /dev/null 2>&1 && echo "  UP" || echo "  DOWN"
done

Générer des Fichiers de Configuration depuis JSON

# Convertir l'inventaire JSON en entrées /etc/hosts
cat inventory.json | jq -r '.hosts[] | "\(.ip)\t\(.hostname)"' >> /etc/hosts

Traitement Conditionnel

#!/bin/bash
status=$(curl -s https://api.example.com/health | jq -r '.status')

if [ "$status" != "healthy" ]; then
    echo "ALERT: Service is $status" | mail -s "Health Check Failed" admin@example.com
fi

Modifier du JSON avec jq

Mettre à Jour des Valeurs

echo '{"version": "1.0", "debug": false}' | jq '.version = "2.0" | .debug = true'
{
  "version": "2.0",
  "debug": true
}

Ajouter des Champs

echo '{"name": "app"}' | jq '. + {"env": "production", "replicas": 3}'

Supprimer des Champs

echo '{"name":"app","secret":"abc123","version":"1.0"}' | jq 'del(.secret)'

Mettre à Jour des Valeurs Imbriquées

echo '{"database":{"host":"old-host","port":5432}}' | jq '.database.host = "new-host"'

Recettes jq du Monde Réel

Analyser le Statut des Pods Kubernetes

kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | "\(.metadata.name)\t\(.status.phase)"'

Extraire les Valeurs de Sortie Terraform

terraform output -json | jq -r 'to_entries[] | "\(.key) = \(.value.value)"'

Analyser les Statistiques de Conteneurs Docker

docker inspect $(docker ps -q) | jq '.[] | {name: .Name, ip: .NetworkSettings.IPAddress, status: .State.Status}'

Traiter les Entrées de Journal CloudWatch

aws logs get-log-events --log-group-name /app/prod --log-stream-name main \
  | jq -r '.events[] | "\(.timestamp | . / 1000 | strftime("%Y-%m-%d %H:%M:%S")) \(.message)"'

Sortie CSV depuis JSON

cat servers.json | jq -r '.servers[] | [.name, .status, (.cpu | tostring)] | @csv'
"web-01","running","45"
"web-02","stopped","0"
"db-01","running","78"

Résolution de Problèmes

“parse error: Invalid numeric literal” : Votre entrée n’est pas du JSON valide. Validez-la d’abord avec jq '.' file.json. Cause courante : l’API a retourné du HTML (page d’erreur) au lieu de JSON.

Sortie “null” alors que vous attendez des données : Le nom du champ est incorrect ou n’existe pas à ce chemin. Utilisez jq 'keys' pour voir les champs disponibles, ou jq '.' | head -20 pour inspecter la structure.

Guillemets dans les assignations de variables : Utilisez toujours jq -r (sortie brute) lors de l’assignation à des variables shell. Sans cela, vous obtenez "value" au lieu de value, ce qui casse les comparaisons de chaînes.

“Cannot iterate over null” : Vous essayez d’itérer (.[]) sur un champ qui est null ou manquant. Ajoutez l’opérateur optionnel : .field[]? ou vérifiez avec select(. != null).

Problèmes d’espaces blancs dans les pipes : Quotez vos variables. echo $json | jq '.' casse sur les espaces blancs. Utilisez plutôt echo "$json" | jq '.'.

Résumé

  • jq est l’outil standard pour le traitement JSON en ligne de commande — un binaire, pas de dépendances, fonctionne partout
  • Utilisez .field, .[index] et .[] pour l’extraction de base ; ajoutez -r pour une sortie de chaîne brute dans les scripts
  • select() filtre les tableaux par condition — prend en charge la correspondance de chaînes, les comparaisons numériques et les regex avec test()
  • Construisez de nouvelles structures JSON avec la construction d’objets {key: .field} et map() pour les transformations de tableaux
  • Combinez avec curl, kubectl, terraform et docker pour l’automatisation en conditions réelles
  • sort_by(), group_by(), length, add gèrent le tri et l’agrégation
  • Modifiez le JSON avec l’assignation (.key = value), l’addition (. + {}), et la suppression (del(.key))
  • Utilisez toujours le flag -r et quotez les variables lors de l’intégration de jq dans des scripts bash

Bash Scripting for Sysadmins: The Essential Guide | Install Security Updates from the Command Line in Ubuntu