web-dev-qa-db-fra.com

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 minutage afin d'évaluer l'impact d'un changement récent de code sur les performances et le débit, mes outils restent les mêmes: grep, awk, sed, tr, uniq, sort, zcat, tail, head, join et split. Pour les coller tous ensemble, Unix nous donne des pipes, et pour un filtrage plus sophistiqué nous avons xargs. Si cela me manque, il y a toujours Perl -e.

Ces outils sont parfaits pour le traitement de fichiers CSV, de fichiers délimités par des tabulations, de fichiers journaux avec un format de ligne prévisible ou de fichiers contenant des paires clé-valeur séparées par des virgules. En d'autres termes, les fichiers où chaque ligne n'a presque pas de contexte.

Analogues 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 complexes, les approches normales s’éclatent. Dites que j'ai des fichiers avec des articles comme celui-ci:

<foo user="me">
    <baz key="zoidberg" value="squid" />
    <baz key="leela"    value="cyclops" />
    <baz key="fry"      value="rube" />
</foo>

Et disons que je veux produire un mappage d'utilisateur à un nombre moyen de <baz>s par <foo>. Le traitement ligne par ligne n’est plus une option. Je dois savoir quel _<foo> de l’utilisateur est en train d’inspecter afin de savoir quelle moyenne mettre à jour. Toute sorte de doublure Unix qui accomplit cette tâche sera probablement impénétrable.

Heureusement, dans XML-land, nous disposons de technologies merveilleuses telles que XPath, XQuery et XSLT pour nous aider.

Auparavant, je m'étais habitué à utiliser le merveilleux module XML::XPath Perl pour effectuer des requêtes comme celle ci-dessus, mais après avoir trouvé un plugin TextMate capable d'exécuter une expression XPath dans ma fenêtre actuelle , j'ai arrêté d'écrire des scripts Perl uniques interroger XML. Et je viens de découvrir XMLStarlet qui est en train d’installer ce que je tape et que j’ai hâte d’utiliser à l’avenir.

Solutions JSON?

Cela me conduit donc à ma question: existe-t-il de tels outils pour JSON? Ce n'est qu'une question de temps avant qu'une tâche d'enquête ne me demande de faire des requêtes similaires sur des fichiers JSON, et sans outils tels que XPath et XSLT, une telle tâche sera beaucoup plus difficile. Si j'avais un groupe de JSON qui ressemblait à 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 de chaque personne, 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 Pouvant "interroger" les fichiers JSON de cette manière?
  2. Si vous devez traiter plusieurs fichiers JSON sur une ligne de commande Unix, quels outils utilisez-vous?
  3. Heck, y a-t-il même du travail en cours de 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'est-ce que vousaimez/aimez en eux? Y a-t-il Des pièges?

Je remarque que de plus en plus de données sont sérialisées à l’aide de JSON. Par conséquent, des outils de traitement de ce type seront essentiels pour l’analyse future de grands volumes de données. 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 est nécessaire de laisser les utilisateurs jouer avec les données.

Questions connexes

56
jasonmp85

Je viens de trouver ceci:

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

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

Mise à jour 2014:

@ user456584 mentionné: 

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

dans la json README à http://github.com/trentm/json il existe une longue liste de choses similaires

51
Brian Tingle

J'ai créé un module spécialement conçu pour la manipulation de 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 jolie imprimante simple ou comme une ligne de commande Javascript pleine de puissance
  • PUISSANT - Expose toute la puissance et la fonctionnalité de underscore.js (plus underscore.string)
  • SIMPLE - Simplifie l'écriture de lignes simples JS similaires à l'utilisation de "Perl -pe"
  • CHAINED - Plusieurs invocations de commande peuvent être chaînées pour créer un pipeline de traitement de données
  • MULTI-FORMAT - Prise en charge étendue des formats d'entrée/sortie - jolies impressions, JSON strict, etc. [à venir]
  • DOCUMENT&EACUTE; - Excellente documentation en ligne de commande avec plusieurs exemples pour chaque commande

Cela 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 possède un très bon système d’aide en ligne de commande et est extrêmement flexible. Il est bien testé et prêt à être utilisé. Cependant, je continue de créer quelques-unes des fonctionnalités telles que les 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 ce message ou ajoutez un problème dans github. J'ai conçu un ensemble de fonctionnalités assez complet, mais je serais ravi de hiérarchiser les fonctionnalités dont les membres de la communauté ont besoin.

7
Dave Dopson

Une façon de le faire est de le convertir en XML. La section suivante utilise deux modules Perl (JSON et XML :: Simple) pour effectuer une conversion directe:

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

qui pour votre exemple json se termine par:

<json age="200" firstName="Bender" lastName="Robot">
  <address city="New York" postalCode="1729" state="NY" streetAddress="123" />
  <phoneNumber number="666 555-1234" type="home" />
  <phoneNumber number="666 555-4567" type="fax" />
</json>
5
azatoth

Regardez ce projet insensé jsawk . Il est conçu pour filtrer via une entrée JSON à partir de la ligne de commande. Vérifiez resty également pour un client en ligne de commande REST que vous pouvez utiliser dans les pipelines pouvant s'avérer utiles.

4
chmeee

Récemment, j'ai découvert que JSON peut facilement être eval- ed 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.

3
newtover

Jetez un coup d'œil à la f:json-document() de la bibliothèque 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 obtenir tous les enfants de Students avec sex = 'Female'

Voici l'exemple complet:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="f xs"
 >
 <xsl:import href="../f/func-json-document.xsl"/>

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vstrParam" as="xs:string">
{

  "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}
       ]
    }


}
 </xsl:variable>

 <xsl:template match="/">
    <xsl:sequence select=
     "f:json-document($vstrParam)/Students/*[sex = 'Female']"/>

 </xsl:template>
</xsl:stylesheet>

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

<Smith>
   <First_Name>Mary</First_Name>
   <sex>Female</sex>
</Smith>
<Jackson>
   <First_Name>Jackie</First_Name>
   <sex>Female</sex>
</Jackson>
2

Heureusement, dans XML-land, nous disposons de technologies merveilleuses telles que XPath, XQuery et XSLT pour nous aider.
[...]
Cela m’amène donc à ma question: existe-t-il de tels outils pour JSON?

Si vous me demandez, Xidel est exactement ce que vous recherchez.

Xidel est un outil de ligne de commande permettant de télécharger et d'extraire des données de pages HTML/XML ou d'API JSON, à l'aide de CSS, XPath 3.0, XQuery 3.0, JSONiq ou de modèles. Il peut également créer des documents XML/HTML/JSON nouveaux ou transformés.

Question:

xidel -s "input.json" \
-e '
  $json/avg(
    count(
      (phoneNumber)()
    )
  )
'

ou

xidel -s "input.json" -e '$json/avg(count((phoneNumber)()))'

Sortie:

2
1
Reino

Il existe également un outil terminal interactif - fx

Pipe dans fx n'importe quelle fonction JSON et anonyme pour la réduire.

$ echo '{...}' | fx [code ...]

Démarrer le mode interactif sans passer d'arguments:

$ curl ... | fx

0
Anton Medvedev