Tracks
/
jq
jq
/
Lehrplan
/
Objekte
Ob

Objekte in jq

4 Übungen

Über Objekte

Ein JSON-Objekt ist, um die Terminologie anderer Sprachen zu verwenden, ein „hash“, ein „map“ oder ein „dictionary“.

JSON definiert ein Objekt so:

Ein Objekt ist eine ungeordnete Menge von Name/Wert-Paaren. Ein Objekt beginnt mit { (linke geschweifte Klammer) und endet mit } (rechte geschweifte Klammer). Auf jeden Namen folgt ein : (Doppelpunkt), und die Name/Wert-Paare werden durch , (Komma) getrennt.

Der Name muss ein String sein. Ein anderes Wort für Name ist Schlüssel.

Der Wert kann von jedem JSON-Typ sein. Verschiedene Werte im selben Objekt können von unterschiedlichen Typen sein, wie in diesem Beispiel.

{
  "name": "Jane",
  "age": 42,
  "pets": ["cat", "fish"],
  "address": {"street": "123 Main St", "city": "Springfield"}
}

Beachte, dass nach dem letzten Schlüssel-Wert-Paar kein Komma stehen darf.

Objekte erstellen

Verwende geschweifte Klammern, um die Name/Wert-Paare zu sammeln. Auch wenn die Namen Strings sein müssen, müssen sie nicht in Anführungszeichen gesetzt werden, wenn die Namen bezeichnerartig sind (aus alphanumerischen Zeichen und Unterstrich zusammengesetzt und nicht mit einer Ziffer beginnend).

{name: "Jane", age: 42}

Es ist zulässig, Schlüssel zu verwenden, die nicht bezeichnerartig sind. Setze sie einfach in Anführungszeichen.

{"first name": "Jane", "last name": "Lopez", age: 42}

Wenn der Name das Ergebnis eines Ausdrucks ist, muss der Ausdruck in Klammern stehen.

$ echo "Jane" | jq -Rc '{.: 42}'
jq: error: syntax error, unexpected '.' (Unix shell quoting issues?) at <top-level>, line 1:
{.: 42}
jq: error: May need parentheses around object key expression at <top-level>, line 1:
{.: 42}
jq: 2 compile errors

$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}

Kurzschreibweisen

Für einige häufige Fälle beim Erstellen von Objekten gibt es eine Kurzschreibweise.

  1. Schlüssel-Wert-Paare aus einem Eingabeobjekt wiederverwenden.

    $ jq -n '$ENV | {USER: .USER, EDITOR: .EDITOR}'
    {
      "USER": "glennj",
      "EDITOR": "vim"
    }
    

    $ENV ist ein Objekt, das die Name-Wert-Paare der Umgebung enthält.

    Die sich wiederholenden Paare key: .key können einfach als key geschrieben werden

    $ jq -n '$ENV | {USER, EDITOR}'
    {
      "USER": "glennj",
      "EDITOR": "vim"
    }
    
  2. Ähnlich gibt es eine Kurzschreibweise bei der Verwendung von Variablen.

    $ jq -cn '"foo" as $a | "bar" as $b | {a: $a, b: $b}'
    {"a":"foo","b":"bar"}
    
    $ jq -cn '"foo" as $a | "bar" as $b | {$a, $b}'
    {"a":"foo","b":"bar"}
    

Indizierung

Werte werden mit der Punktnotation aus einem Objekt abgerufen.

{name: "Jane", age: 42} | .age    # => 42

Wenn du den Schlüssel nicht als Bezeichner angeben kannst, verwendest du die Notation mit eckigen Klammern.

"name" as $key | {name: "Jane", age: 42} | .$key    # => error
"name" as $key | {name: "Jane", age: 42} | .[$key]  # => "Jane"

Wenn der Schlüssel nicht im Objekt enthalten ist, ist das Ergebnis null.

{name: "Jane", age: 42} | .sport  # => null

Indizierung verschachtelter Werte

Du wirst feststellen, dass du das beim Auswerten der Ergebnisse von API-Abfragen immer wieder tun musst.

Bei einem Objekt, das Array- oder Objektwerte enthält, können wir Indexausdrücke miteinander „verketten“.

{
  "name": "Jane",
  "age": 42,
  "pets": ["cat", "fish"],
  "address": {"street": "123 Main St", "city": "Springfield"}
}
| (
  .pets[1],       # => "fish"
  .address.city   # => "Springfield"
)

Schlüssel-Wert-Paare hinzufügen oder ändern

Um einem Array ein neues Schlüssel-Wert-Paar hinzuzufügen oder den Wert eines vorhandenen Schlüssels zu aktualisieren, verwendest du den Zuweisungsoperator =, mit einem Indexausdruck auf der linken Seite.

{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
#      "name": "Jane",
#      "age": 21,
#      "sport": "tennis"
#    }

Mit dem +-Operator lassen sich Objekte zusammenführen.

{Richard: 54} + {Jane: 42}
# => {
#      "Richard": 54,
#      "Jane": 42
#    }

Einen Schlüssel entfernen

Verwende die Funktion del, um einen Schlüssel zu entfernen. Sie gibt das aktualisierte Objekt zurück.

{name: "Jane", age: 42} | del(.age)   # => {"name": "Jane"}

Der Parameter von del ist ein Indexausdruck (in Punkt- oder Klammernotation), der sich zu einem Schlüssel im Objekt auflöst. jq nennt ihn einen Pfadausdruck. Es reicht nicht, einfach einen String anzugeben.

{name: "Jane", age: 42} | del(name)        # error: name/0 is not defined
{name: "Jane", age: 42} | del("name")      # error: Invalid path expression with result "name"
{name: "Jane", age: 42} | del(.name)       # OK
{name: "Jane", age: 42} | del(.["name"])   # OK

Prüfen, ob ein Schlüssel enthalten ist

  • Um zu prüfen, ob das Objekt einen Schlüssel enthält, verwendest du die Funktion has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Mit in prüfst du, ob ein Schlüssel in einem Objekt enthalten ist.

    {name: "Jane", age: 42} as $example
    |
      ("name"  | in($example)),    # => true
      ("sport" | in($example))     # => false
    

Die Schlüssel oder Werte auflisten

Verwende die Funktion keys, um eine Liste aller Schlüssel auszugeben.

{name: "Jane", age: 42} | keys   # => ["age", "name"]

Beachte, dass keys die Schlüssel sortiert. Um die Schlüssel in der ursprünglichen Reihenfolge zu erhalten, verwendest du keys_unsorted.

Es gibt keine entsprechende Funktion, um alle Werte aufzulisten. Der Filter .[] gibt die Objektwerte jedoch als Stream aus, und dieser Stream kann mit dem Array-Konstruktor [...] eingefangen werden.

[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]

Iterieren

  • Die Funktion map_values(filter) wendet den Filter auf jeden Wert im Objekt an.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Um über ein Objekt zu iterieren, müssen wir es zuerst in ein Array von Schlüssel-Wert-Objekten umwandeln. Die Funktion to_entries macht genau das.

    {name: "Jane", age: 42} | to_entries
    # => [
    #      {
    #        "key": "name",
    #        "value": "Jane"
    #      },
    #      {
    #        "key": "age",
    #        "value": 42
    #      }
    #    ]
    

    An dieser Stelle können wir Array-Iterationsfunktionen wie map verwenden.

  • Die Funktion from_entries ist die Umkehrung: Sie wandelt ein Array von Schlüssel-Wert-Objekten in ein Objekt um.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # => {"name": "Jane", "age": 42}
    
  • Um einen Filter auf jedes Schlüssel-Wert-Paar in einem Objekt anzuwenden, verwendest du die Funktion with_entries(filter).

    Zum Beispiel: Bei einem Objekt, das einen Namen auf ein Alter abbildet, lassen sich Schlüssel und Werte wie folgt vertauschen.

    {"Jane": 42, "Richard": 54}
    | with_entries({key: (.value | tostring), value: .key})
    

    gibt aus

    {
      "42": "Jane",
      "54": "Richard"
    }
    

    with_entries(filter) entspricht

    to_entries | map(filter) | from_entries
    
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab

Lerne Objekte

Das Üben ist gesperrt

Schalte 4 weitere Übungen frei, um Objekte zu üben