Quels sont les bons outils CLI pour JSON?

Problème général

Bien que je puisse diagnostiquer la cause première d’un événement, déterminer le nombre d’utilisateurs concernés ou distiller des journaux de temps afin d’évaluer les performances et l’impact d’un changement de code récent, mes outils restnt les mêmes: grep , awk , sed , tr , uniq , sort , zcat , tail , head , join et split . Pour les coller tous ensemble, Unix nous donne des tuyaux, et pour un filtrage plus sophistiqué, nous avons xargs . Si ceux-ci me manquent, il y a toujours perl -e .

Ces outils sont parfaits pour traiter des fichiers CSV, des fichiers délimités par des tabulations, des fichiers journaux avec un format de ligne prévisible ou des fichiers avec des paires clé-valeur séparées par des virgules. En d’autres termes, des fichiers où chaque ligne n’a pratiquement aucun contexte.

Analog XML

J’ai récemment eu besoin de parcourir des gigaoctets de XML pour créer un histogramme d’utilisation par utilisateur. C’était assez facile avec les outils que j’avais, mais pour les requêtes plus compliquées, les approches normales se décomposent. Disons que j’ai des fichiers avec des éléments comme celui-ci:

      

Et disons que je veux produire un mappage du nombre d’utilisateurs à un nombre moyen de s par . Le traitement ligne à ligne n’est plus une option: j’ai besoin de savoir de quel utilisateur je suis en train d’inspecter et je sais donc quelle moyenne mettre à jour. Toute sorte de ligne Unix qui accomplit cette tâche est susceptible d’être impénétrable.

Heureusement, dans XML-land, nous avons de formidables technologies comme XPath, XQuery et XSLT pour nous aider.

Auparavant, je m’étais habitué à utiliser le merveilleux module XML::XPath Perl pour accomplir des requêtes comme celle ci-dessus, mais après avoir trouvé un plug-in TextMate capable d’exécuter une expression XPath dans ma fenêtre actuelle , j’ai arrêté d’écrire des scripts Perl uniques. requête XML. Et je viens de découvrir XMLStarlet qui s’installe au fur et à mesure que je tape ceci et que j’espère pouvoir utiliser à l’avenir.

Solutions JSON?

Donc, cela m’amène à ma question: existe-t-il des outils comme celui-ci pour JSON? Ce n’est qu’une question de temps avant que certaines tâches d’investigation ne me demandent de faire des requêtes similaires sur des fichiers JSON, et sans les outils XPath et XSLT, une telle tâche sera beaucoup plus difficile. Si j’avais un tas de JSON qui ressemblaient à ceci:

 { "firstName": "Bender", "lastName": "Robot", "age": 200, "address": { "streetAddress": "123", "city": "New York", "state": "NY", "postalCode": "1729" }, "phoneNumber": [ { "type": "home", "number": "666 555-1234" }, { "type": "fax", "number": "666 555-4567" } ] } 

Et je voulais trouver le nombre moyen de numéros de téléphone que chaque personne avait, je pourrais faire quelque chose comme ça avec XPath:

 fn:avg(/fn:count(phoneNumber)) 

Des questions

  1. Existe-t-il des outils de ligne de commande capables d’interroger les fichiers JSON de cette manière?
  2. Si vous devez traiter un tas de fichiers JSON sur une ligne de commande Unix, quels outils utilisez-vous?
  3. Heck, y at-il même du travail pour créer un langage de requête comme celui-ci pour JSON?
  4. Si vous utilisez des outils comme celui-ci dans votre travail quotidien, qu’aimez-vous / détestez-vous à leur sujet? Y a-t-il des pièges?

Je remarque que de plus en plus de sérialisation de données est effectuée à l’aide de JSON, de sorte que des outils de traitement comme celui-ci seront cruciaux lors de l’parsing de sauvegardes de données volumineuses à l’avenir. Les bibliothèques de langues pour JSON sont très puissantes et il est assez facile d’écrire des scripts pour effectuer ce type de traitement, mais il faut vraiment laisser les utilisateurs jouer avec les outils de shell de données.

questions connexes

  • Equivalent Grep et Sed pour le traitement de ligne de commande XML
  • Existe-t-il un langage de requête pour JSON?
  • JSONPath ou autre utilitaire de type XPath pour JSON / Javascript; ou Jquery JSON

Je viens de trouver ceci:

http://stedolan.github.com/jq/

“jq est un processeur JSON de ligne de commande léger et flexible.”

2014 mise à jour:

@ user456584 a mentionné:

Il y a aussi la commande ‘json’ (par exemple, ‘jsontool’). J’ai tendance à préférer ça au jq. Très UNIX-y. Voici un lien vers le projet: github.com/trentm/json –

dans le README json à http://github.com/trentm/json il y a une longue liste de choses similaires

J’ai créé un module spécialement conçu pour la manipulation JSON en ligne de commande:

https://github.com/ddopson/underscore-cli

  • FLEXIBLE – L’outil “swiss-army-knife” pour le traitement des données JSON – peut être utilisé comme une simple imprimante ou comme une ligne de commande Javascript complète
  • PUISSANT – Expose toute la puissance et les fonctionnalités de underscore.js (plus underscore.ssortingng)
  • SIMPLE – Facilite l’écriture des lignes JS similaires à l’utilisation de “perl -pe”
  • CHAINED – Plusieurs invocations de commandes peuvent être chaînées pour créer un pipeline de traitement de données
  • MULTI-FORMAT – Support riche pour les formats d’entrée / sortie – jolie impression, JSON ssortingct, etc. [bientôt disponible]
  • DOCUMENTED – Excellente documentation en ligne de commande avec plusieurs exemples pour chaque commande

Il vous permet de faire des choses puissantes très facilement:

 cat earthporn.json | underscore select '.data .title' # [ 'Fjaðrárgljúfur canyon, Iceland [OC] [683x1024]', # 'New town, Edinburgh, Scotland [4320 x 3240]', # 'Sunrise in Bryce Canyon, UT [1120x700] [OC]', # ... # 'Kariega Game Reserve, South Africa [3584x2688]', # 'Valle de la Luna, Chile [OS] [1024x683]', # 'Frosted trees after a snowstorm in Laax, Switzerland [OC] [1072x712]' ] cat earthporn.json | underscore select '.data .title' | underscore count # 25 underscore map --data '[1, 2, 3, 4]' 'value+1' # prints: [ 2, 3, 4, 5 ] underscore map --data '{"a": [1, 4], "b": [2, 8]}' '_.max(value)' # [ 4, 8 ] echo '{"foo":1, "bar":2}' | underscore map -q 'console.log("key = ", key)' # key = foo # key = bar underscore pluck --data "[{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}]" name # [ 'moe', 'larry', 'curly' ] underscore keys --data '{name : "larry", age : 50}' # [ 'name', 'age' ] underscore reduce --data '[1, 2, 3, 4]' 'total+value' # 10 

Il dispose d’un système d’aide en ligne de commande très flexible et extrêmement flexible. Il est bien testé et prêt à l’emploi; Cependant, je continue à développer quelques fonctionnalités telles que des alternatives pour le format d’entrée / sortie et la fusion dans mon outil de gestion de modèles (voir TODO.md). Si vous avez des demandes de fonctionnalités, commentez cet article ou ajoutez un problème dans github. J’ai conçu un ensemble de fonctionnalités très complet, mais je serais ravi de hiérarchiser les fonctionnalités requirejses par les membres de la communauté.

Une des façons de le faire est de le convertir en XML. La section suivante utilise deux modules perl (JSON et XML :: Simple) pour effectuer une conversion rapide:

 cat test.json | perl -MJSON -MXML::Simple -e 'print XMLout(decode_json(do{local$/;<>}),RootName=>"json")' 

qui pour votre exemple json se retrouve comme:

  

Jetez un oeil à ce projet fou jsawk . Il est conçu pour filtrer via une entrée JSON à partir de la ligne de commande. Vérifiez également la disponibilité d’un client REST en ligne de commande que vous pouvez utiliser dans des pipelines utiles.

Récemment, j’ai découvert que JSON peut facilement être évalué avec Python:

 $ python -c "json=eval(open('/json.txt').read()); print len(json['phoneNumber'])" 2 

Bien que la méthode échoue évidemment si l’entrée JSON contient des valeurs NULL.

Jetez un coup d’oeil au f:json-document() de la librairie FXSL 2.x.

En utilisant cette fonction, il est extrêmement facile d’incorporer JSon et de l’utiliser comme … XML.

Par exemple, il suffit d’écrire l’expression XPath suivante:

 f:json-document($vstrParam)/Students/*[sex = 'Female'] 

et amène tous les enfants des Students avec le sex = 'Female'

Voici l’exemple complet:

     { "teacher":{ "name": "Mr Borat", "age": "35", "Nationality": "Kazakhstan" }, "Class":{ "Semester": "Summer", "Room": null, "Subject": "Politics", "Notes": "We're happy, you happy?" }, "Students": { "Smith": {"First Name":"Mary","sex":"Female"}, "Brown": {"First Name":"John","sex":"Male"}, "Jackson": {"First Name":"Jackie","sex":"Female"} } , "Grades": { "Test": [ {"grade":"A","points":68,"grade":"B","points":25,"grade":"C","points":15}, {"grade":"C","points":2, "grade":"B","points":29, "grade":"A","points":55}, {"grade":"C","points":2, "grade":"A","points":72, "grade":"A","points":65} ] } }      

Lorsque la transformation ci-dessus est appliquée à un document XML (ignoré), le résultat correct est généré :

  Mary Female   Jackie Female