Tracce
/
jq
jq
/
Programma
/
Oggetti
Og

Oggetti in jq

4 esercizi

Informazioni su Oggetti

Un oggetto JSON è, per usare la terminologia di altri linguaggi, un «hash», una «map» o un «dictionary».

JSON definisce un oggetto così:

Un oggetto è un insieme non ordinato di coppie nome/valore. Un oggetto inizia con { (parentesi graffa aperta) e termina con } (parentesi graffa chiusa). Ogni nome è seguito da : (due punti) e le coppie nome/valore sono separate da , (virgola).

Il nome deve essere una stringa. Un altro termine per nome è chiave.

Il valore può essere di qualsiasi tipo JSON. Valori diversi nello stesso oggetto possono essere di tipi diversi, come in questo esempio.

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

Nota che non deve esserci una virgola dopo l'ultima coppia chiave-valore.

Creare oggetti

Usa le parentesi graffe per raccogliere le coppie nome/valore. Anche se i nomi devono essere stringhe, non è necessario racchiuderli tra virgolette se sono simili a identificatori (composti da caratteri alfanumerici e underscore, e non iniziano con una cifra).

{name: "Jane", age: 42}

È valido usare chiavi che non sono simili a identificatori. Basta racchiuderle tra virgolette.

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

Se il nome è il risultato di un'espressione, l'espressione deve essere tra parentesi.

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

Notazioni abbreviate

Un paio di casi frequenti nella costruzione di oggetti hanno una sintassi abbreviata.

  1. Riutilizzare coppie chiave-valore da un oggetto di input.

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

    $ENV è un oggetto che contiene le coppie nome-valore dell'ambiente.

    Le ripetitive coppie key: .key si possono scrivere semplicemente come key

    $ jq -n '$ENV | {USER, EDITOR}'
    {
      "USER": "glennj",
      "EDITOR": "vim"
    }
    
  2. Allo stesso modo, esiste una forma abbreviata quando si usano le variabili.

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

Indicizzazione

I valori si recuperano da un oggetto con la notazione con il punto.

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

Se non puoi fare riferimento alla chiave come a un identificatore, usa la notazione con le parentesi.

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

Se la chiave non è presente nell'oggetto, il risultato è null.

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

Indicizzare valori annidati

Scoprirai che questa è un'azione che devi ripetere più e più volte quando analizzi i risultati delle query API.

Dato un oggetto che contiene valori di tipo array o oggetto, possiamo «concatenare» tra loro le espressioni di indicizzazione.

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

Aggiungere o modificare coppie chiave-valore

Per aggiungere una nuova coppia chiave-valore a un array, o per aggiornare il valore di una chiave esistente, usa l'operatore di assegnazione =, con un'espressione di indicizzazione sul lato sinistro.

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

L'operatore + unisce gli oggetti.

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

Rimuovere una chiave

Usa la funzione del per rimuovere una chiave. Restituisce l'oggetto aggiornato.

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

Il parametro di del è un'espressione di indicizzazione (che usa la notazione con il punto o con le parentesi) che si risolve in una chiave dell'oggetto. jq la chiama espressione di percorso. Non basta fornire una semplice stringa.

{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

Appartenenza

  • Per verificare se l'oggetto ha una chiave, usa la funzione has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Verifica se una chiave è presente in un oggetto con in.

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

Elencare le chiavi o i valori

Usa la funzione keys per produrre un elenco di tutte le chiavi.

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

Nota che keys ordina le chiavi. Per recuperare le chiavi nell'ordine originale, usa keys_unsorted.

Non esiste una funzione equivalente per elencare tutti i valori. Tuttavia il filtro .[] restituisce i valori dell'oggetto come flusso, e quel flusso può essere catturato con il costruttore di array [...].

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

Iterare

  • La funzione map_values(filter) applica il filtro a ciascun valore dell'oggetto.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Per iterare su un oggetto, dobbiamo prima convertirlo in un array di oggetti chiave-valore. La funzione to_entries fa questo.

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

    A questo punto, possiamo usare le funzioni di iterazione sugli array, come map.

  • La funzione from_entries è l'inversa: converte un array di oggetti chiave-valore in un oggetto.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # => {"name": "Jane", "age": 42}
    
  • Per applicare un filtro a ciascuna coppia chiave-valore di un oggetto, usa la funzione with_entries(filter).

    Per esempio, dato un oggetto che associa un nome a un'età, le chiavi e i valori si possono scambiare in questo modo.

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

    produce

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

    with_entries(filter) equivale a

    to_entries | map(filter) | from_entries
    
Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda

Impara Oggetti

La pratica è bloccata

Sblocca 4 altri esercizi per esercitarti su Oggetti