Un oggetto JSON è, per usare la terminologia di altri linguaggi, un «hash», una «map» o un «dictionary».
JSON definisce un oggetto come:
Un oggetto è un insieme non ordinato di coppie nome/valore. Un oggetto inizia con la parentesi graffa aperta
{e termina con la parentesi graffa chiusa}. Ogni nome è seguito dai due punti (:) e le coppie nome/valore sono separate da una 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"}
}
Tieni presente che non deve esserci una virgola dopo l'ultima coppia chiave-valore.
Usa le parentesi graffe per raccogliere le coppie nome/valore. Anche se i nomi devono essere stringhe, non è necessario metterli tra virgolette se sono identifier-like (composti da caratteri alfanumerici e underscore, e non iniziano con una cifra).
{name: "Jane", age: 42}
È valido usare chiavi che non sono identifier-like. Basta metterle 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}'
# verbose error message ...
$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}
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"
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 indice sul lato sinistro.
{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
# "name": "Jane",
# "age": 21,
# "sport": "tennis"
# }
L'operatore + fonde gli oggetti.
{Richard: 54} + {Jane: 42}
# => {
# "Richard": 54,
# "Jane": 42
# }
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 indice (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
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
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 .[] produce i valori dell'oggetto come stream, e quello stream può essere catturato con il costruttore di array [...].
[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]
La funzione map_values(filter) applica il filtro a ogni 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 degli array, come map.
La funzione from_entries è l'inverso: 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 ogni 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 possono essere scambiati come segue.
{"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
In questo esercizio implementerai un modo per tenere traccia dei punteggi più alti del gioco più popolare della tua sala giochi locale.
Devi implementare 6 funzioni, per lo più legate alla manipolazione di un oggetto che contiene i punteggi più alti.
Scrivi una funzione create_score_board che crea un oggetto che funge da classifica dei punteggi più alti.
Le chiavi di questo oggetto saranno i nomi dei giocatori, i valori saranno i loro punteggi.
Per i test, vuoi includere direttamente una voce nell'oggetto.
Questa voce iniziale deve consistere di "The Best Ever" come nome del giocatore e 1000000 come punteggio.
create_score_board
# returns an object with one initial entry
Per aggiungere un giocatore alla classifica dei punteggi più alti, implementa la funzione add_player.
Prende in input una classifica e richiede due parametri: il nome del giocatore e il suo punteggio.
La funzione dà in output l'oggetto classifica con il nuovo giocatore aggiunto.
{"José Valim", 486373}
| add_player("Dave Thomas"; 0)
# => {"Dave Thomas": 0, "José Valim": 486373} -- in some order
Se il giocatore è già presente nella classifica, dai in output la classifica invariata.
Se i giocatori violano le regole della sala giochi, vengono rimossi manualmente dalla classifica dei punteggi più alti.
Implementa remove_player, che prende in input una classifica e un parametro: il nome del giocatore da rimuovere.
Questa funzione deve rimuovere la voce del giocatore indicato dalla classifica e dare in output la nuova classifica.
Se il giocatore non era presente nella classifica, non deve succedere nulla alla classifica: deve essere restituita così com'è.
{"Dave Thomas": 0} | remove_player("Dave Thomas")
# => {}
{"Dave Thomas": 0} | remove_player("Rose Fanaras")
# => {"Dave Thomas": 0}
Se un giocatore termina un'altra partita alla sala giochi, una certa quantità di punti verrà aggiunta al punteggio precedente nella classifica.
Implementa update_score, che prende in input una classifica e richiede due parametri: il nome del giocatore e la quantità di punteggio da aggiungere.
La funzione deve restituire la classifica dopo l'aggiornamento.
{"Freyja Ćirić": 12771000} | update_score("Freyja Ćirić"; 73)
# => {"Freyja Ćirić": 12771073}
Questa funzione deve aggiungere il giocatore alla classifica se non era già presente.
La sala giochi tiene una classifica separata il lunedì. Alla fine della giornata, ogni giocatore su quella classifica riceve 100 punti aggiuntivi.
Implementa la funzione apply_monday_bonus.
La funzione aggiunge i punti bonus a ogni giocatore elencato in quella classifica.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| apply_monday_bonus
# => {"Dave Thomas": 144, "Freyja Ćirić": 639, "José Valim": 365}
Sala giochi diverse competono tra loro per determinare chi ha i giocatori migliori. La sala giochi con il punteggio totale più alto vince l'onore.
Scrivi una funzione total_score.
Prende in input una classifica e dà in output la somma dei punteggi di tutti i giocatori.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| total_score
# => 848
Iscriviti a Exercism per imparare e padroneggiare jq con 12 concetti75 esercizi e il mentoring di persone reali, tutto gratis.