Manipuler des JSON en ligne de commande grace à JQ exemple avec cURL

Je n'utilise quasiment plus que la ligne de commande pour faire des appels sur des APIs en utilisant cURL. C'est pratique et rapide, facilement scriptable si besoin et l'historique du bash me permet de gagner du temps. Seulement la réponse fournie par cURL n'est pas toujours très lisible surtout quand il s'agit de JSON.

Pour formater la réponse de cURL et avoir un JSON lisible j'utilise l'outil jq. Cette lib est disponible pour beaucoup de distrib linux en paquet mais aussi pour Mac et Windows. Sur Debian, le paquet est disponible sans besoin d'ajouter un nouveau repo au source.list.


EDIT: Si les exemples failed lancer la commande curl avec l'option -I , si vous obtenez une erreur 403 il faut changer la string après l'option -A.


> apt-get install jq


Pour illustrer les commandes je vais utiliser l'API du site Have I been pwned. Un appel classique avec cURL donne se résultat.

> curl -X GET -A mon-code.net-exemple https://haveibeenpwned.com/api/v2/breachedaccount/john@doe.com
 


[{"Title":"000webhost","Name":"000webhost","Domain":"000webhost.com","BreachDate":"2015-03-01","AddedDate":"2015-10-26T23:35:45Z"
,"ModifiedDate":"2015-10-26T23:35:45Z","PwnCount":13545468,
"Description":"In approximately March 2015, the free web hosting 
provider <a href=\"http://www.troyhunt.com/2015/10/breaches-traders-plain-text-passwords.html\" target=\"_blank\"
 
rel=\"noopener\">000webhost suffered a major data breach</a> that exposed over 13 million customer records. The data was sold 
and traded before 000webhost was alerted in October. 
The breach included names, email addresses and plain text passwords.",
"DataClasses":["Email addresses","IP addresses","Names","Passwords"],"IsVerified":true,"IsFabricated":false,"IsSensitive":false,
"IsActive":true,"IsRetired":false,"IsSpamList":false,"LogoType":"png"},{"Title":"Acne.org","Name":"AcneOrg","Domain":"acne.org",
"BreachDate":"2014-11-25","AddedDate":"2016-03-06T11:07:41Z","ModifiedDate":"2016-03-06T11:07:41Z","PwnCount":432943,"Description"
:"In November 2014, the acne website <a href=\"http://www.acne.org/\" target=\"_blank\" rel=\"noopener\">acne.org</a>...


En ajoutant jq à la commande on obtient une résultat beaucoup plus lisible.

> curl -X GET -A mon-code.net-exemple https://haveibeenpwned.com/api/v2/breachedaccount/john@doe.com | jq .
 


[
  {
    "Title": "000webhost",
    "Name": "000webhost",
    "Domain": "000webhost.com",
    "BreachDate": "2015-03-01",
    "AddedDate": "2015-10-26T23:35:45Z",
    "ModifiedDate": "2015-10-26T23:35:45Z",
    "PwnCount": 13545468,
    "Description": "In approximately March 2015, the free web hosting provider <a href=\"http://www.troyhunt.com/2015/10/breaches-traders-plain-text-passwords.html\" target=\"_blank\" rel=\"noopener\">000webhost suffered a major data breach</a> that exposed over 13 million customer records. The data was sold and traded before 000webhost was alerted in October. The breach included names, email addresses and plain text passwords.",
    "DataClasses": [
      "Email addresses",
      "IP addresses",
      "Names",
      "Passwords"
    ],
    "IsVerified": true,
    "IsFabricated": false,
    "IsSensitive": false,
    "IsActive": true,
    "IsRetired": false,
    "IsSpamList": false,
    "LogoType": "png"
  },
....]


C'est beaucoup plus lisible mais jq permet d'aller plus en appliquant des filtres. Si par exemple je ne souhaite avoir que la liste des domaines qui ont exposé l'adresse john@doe.com il me suffit d'ajouter un filtre à la commande jq.

> curl -X GET -A mon-code.net-exemple https://haveibeenpwned.com/api/v2/breachedaccount/john@doe.com | jq '.[].Domain'
"000webhost.com"
"acne.org"
"adobe.com"
"armyforceonline.com"
"cheapassgamer.com"
"dailymotion.com"
"dropbox.com"
"edmodo.com"
"elance.com"
"evony.com"
"ffshrine.org"
...


Toujours pas séduit par jq? Il est possible de créer son propre Json en piochant dans les données du Json fournis. Ainsi je peux associer le domaine avec le type d'exposition.

> curl -X GET -A mon-code.net-exemple https://haveibeenpwned.com/api/v2/breachedaccount/john@doe.com | jq '[{(.[].Domain): .[].DataClasses}]'
[{
  "000webhost.com": [
    "Email addresses",
    "IP addresses",
    "Names",
    "Passwords"
  ]
},
{
  "000webhost.com": [
    "Dates of birth",
    "Email addresses",
    "IP addresses",
    "Passwords",
    "Usernames"
  ]
},
...]
 

Notez les '()' autour de l'expression que j'utilise pour extraire le domaine. Elle permettent de l'évaluer car je veux m'en servir de clé, sinon jq s'attend à une simple string.

Jq permet beaucoup d'autres manipulations, je vous invite à parcourir la doc qui est très bien faite. Et pour ceux qui souhaitent tester sans utiliser d'API on peut utiliser jq play pour ça.

Ajouter un commentaire