it-swarm.com.de

Was sind gute CLI-Tools für JSON?

Allgemeines Problem

Obwohl ich möglicherweise die Grundursache eines Ereignisses diagnostiziere, feststelle, wie viele Benutzer davon betroffen sind, oder Timing-Protokolle destilliere, um die Leistung und den Durchsatz einer kürzlich vorgenommenen Codeänderung zu bewerten, bleiben meine Tools unverändert: grep, awk, sed, tr, uniq, sort, zcat, tail, head, join und split. Um sie alle zusammenzukleben, gibt Unix uns Pipes und für eine ausgefeiltere Filterung haben wir xargs. Wenn diese fehlschlagen, gibt es immer Perl -e.

Diese Tools eignen sich perfekt für die Verarbeitung von CSV-Dateien, tabulatorgetrennten Dateien, Protokolldateien mit einem vorhersagbaren Zeilenformat oder Dateien mit durch Kommas getrennten Schlüssel-Wert-Paaren. Mit anderen Worten, Dateien, bei denen jede Zeile neben keinem Kontext steht.

XML-Analoga

Vor kurzem musste ich Gigabyte XML durchsuchen, um ein Nutzungshistogramm für den Benutzer zu erstellen. Das war mit den Tools, die ich hatte, recht einfach, aber für kompliziertere Abfragen gehen die normalen Ansätze kaputt. Angenommen, ich habe Dateien mit folgenden Elementen:

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

Angenommen, ich möchte eine Zuordnung zwischen Benutzer und durchschnittlicher Anzahl von <baz>s pro <foo> erstellen. Die zeilenweise Verarbeitung ist keine Option mehr: Ich muss wissen, welchen <foo> des Benutzers ich gerade überprüfe, damit ich weiß, wessen Durchschnitt aktualisiert werden muss. Jede Art von Unix-One-Liner, die diese Aufgabe erfüllt, ist wahrscheinlich unergründlich.

Glücklicherweise stehen uns in XML-Land wunderbare Technologien wie XPath, XQuery und XSLT zur Verfügung.

Früher hatte ich mich daran gewöhnt, mit dem wunderbaren Perl-Modul XML::XPath Abfragen wie die oben genannten durchzuführen. Nachdem ich jedoch ein TextMate-Plugin gefunden hatte, mit dem ein XPath-Ausdruck für mein aktuelles Fenster ausgeführt werden konnte , schrieb ich keine einmaligen Perl-Skripte mehr um XML abzufragen. Und ich habe gerade von XMLStarlet erfahren, das während der Eingabe installiert wird und auf das ich mich in Zukunft freue.

JSON-Lösungen?

Das führt mich zu meiner Frage: Gibt es solche Tools für JSON? Es ist nur eine Frage der Zeit, bis ich bei einer Nachforschungsaufgabe ähnliche Abfragen für JSON-Dateien durchführen muss. Ohne Tools wie XPath und XSLT wird eine solche Aufgabe sehr viel schwieriger. Wenn ich einen Haufen JSON hätte, der so aussähe:

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

Und um die durchschnittliche Anzahl der Telefonnummern zu ermitteln, die jede Person hatte, konnte ich mit XPath Folgendes tun:

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

Fragen

  1. Gibt es Befehlszeilentools, mit denen JSON-Dateien auf diese Weise abgefragt werden können?
  2. Welche Tools verwenden Sie, wenn Sie eine Reihe von JSON-Dateien in einer Unix-Befehlszeile verarbeiten müssen?
  3. Was soll's, wird überhaupt daran gearbeitet, eine solche Abfragesprache für JSON zu erstellen?
  4. Wenn Sie in Ihrer täglichen Arbeit Werkzeuge wie dieses verwenden, was mögen/nicht mögen Sie an ihnen? Gibt es irgendwelche Fallstricke?

Ich stelle fest, dass immer mehr Daten mit JSON serialisiert werden. Daher sind solche Verarbeitungstools für die Analyse großer Datenmengen in Zukunft von entscheidender Bedeutung. Sprachbibliotheken für JSON sind sehr stark und es ist einfach genug, Skripte zu schreiben, um diese Art der Verarbeitung durchzuführen, aber um wirklich mit den Daten herumspielen zu können, werden Shell-Tools benötigt.

Verwandte Fragen

56
jasonmp85

Ich habe gerade das gefunden:

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

"jq ist ein leichter und flexibler Befehlszeilen-JSON-Prozessor."

Update 2014:

@ user456584 erwähnt: 

Es gibt auch den Befehl 'json' (z. B. 'jsontool'). Ich ziehe es vor, jq zu bevorzugen. Sehr UNIX-y. Hier ist ein Link zum Projekt: github.com/trentm/json - 

in derjsonREADME unter http://github.com/trentm/json gibt es eine lange Liste ähnlicher Dinge

51
Brian Tingle

Ich habe ein Modul erstellt, das speziell für die Befehlszeilen-JSON-Manipulation entwickelt wurde:

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

  • FLEXIBLE- Das "Swiss-Army-Knife" -Tool zur Verarbeitung von JSON-Daten - kann als einfacher Pretty-Printer oder als vollwertige Javascript-Befehlszeile verwendet werden
  • LEISTUNGSSTARKE- Zeigt die volle Leistungsfähigkeit und Funktionalität von underscore.js (und Underscore.string) an.
  • SIMPLE- Macht das Schreiben von JS-Einzeilen ähnlich wie bei "Perl -pe" einfach.
  • VERKETTET- Mehrere Befehlsaufrufe können miteinander verkettet werden, um eine Datenverarbeitungspipeline zu erstellen
  • MULTI-FORMAT - Umfangreiche Unterstützung für Eingabe-/Ausgabeformate - hübsches Drucken, strenges JSON usw. [in Kürze]
  • DOKUMENTIERT- Ausgezeichnete Befehlszeilendokumentation mit mehreren Beispielen für jeden Befehl

Es erlaubt Ihnen, sehr leicht mächtige Dinge zu tun:

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

Es hat ein sehr schönes Befehlszeilen-Hilfesystem und ist extrem flexibel. Es ist gut getestet und einsatzbereit. Ich baue jedoch noch einige Funktionen auf, z. B. Alternativen für das Eingabe-/Ausgabeformat und das Zusammenführen in meinem Vorlagenbehandlungstool (siehe TODO.md). Wenn Sie Funktionsanfragen haben, kommentieren Sie diesen Beitrag oder fügen Sie ein Problem in github hinzu. Ich habe ein ziemlich umfangreiches Feature-Set entworfen, aber ich würde mich freuen, Funktionen zu priorisieren, die von Mitgliedern der Community benötigt werden.

7
Dave Dopson

Eine Möglichkeit, dies zu tun, ist die Konvertierung in XML. Folgendes verwendet zwei Perl-Module (JSON und XML :: Simple) für die Fly-by-Konvertierung:

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

was für Ihr Beispiel json endet als:

<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

Schauen Sie sich dieses verrückte Projekt jsawk an. Die JSON-Eingabe wird von der Befehlszeile aus gefiltert. Überprüfen Sie resty auch für einen Befehlszeile-REST -Client, den Sie in Pipelines verwenden können, die sich als nützlich erweisen können.

4
chmeee

Vor kurzem entdeckte ich, dass JSON leicht mit Python eval- __- verbunden werden kann:

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

Die Methode schlägt jedoch offensichtlich fehl, wenn die JSON-Eingabe Nullen enthält.

3
newtover

Schauen Sie sich die f:json-document() aus der FXSL 2.x-Bibliothek an.

Mit dieser Funktion ist es sehr einfach, JSon einzubinden und genauso wie ... XML zu verwenden.

Zum Beispiel kann man einfach den folgenden XPath-Ausdruck schreiben:

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

und holt alle Kinder von Students mit sex = 'Female'

Hier ist das vollständige Beispiel:

<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>

Wenn die obige Transformation auf ein XML-Dokument angewendet wird (ignoriert), wird das korrekte Ergebnis erzeugt :

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

Glücklicherweise stehen uns in XML-Land wunderbare Technologien wie XPath, XQuery und XSLT zur Verfügung.
[...]
Das führt mich zu meiner Frage: Gibt es solche Tools für JSON?

Wenn Sie mich fragen, ist Xidel genau das, wonach Sie suchen.

Xidel ist ein Befehlszeilentool zum Herunterladen und Extrahieren von Daten aus HTML/XML-Seiten oder JSON-APIs mit CSS, XPath 3.0, XQuery 3.0, JSONiq oder Mustervorlagen. Es kann auch neue oder transformierte XML/HTML/JSON-Dokumente erstellen.

Abfrage:

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

oder

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

Ausgabe:

2
1
Reino

Es gibt auch ein interaktives Terminal-Tool - fx

Fügen Sie eine beliebige JSON- und anonyme Funktion hinzu, um sie zu reduzieren.

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

Starten Sie den interaktiven Modus, ohne Argumente zu übergeben:

$ curl ... | fx

0
Anton Medvedev