Un objet JSON est, pour reprendre la terminologie d'autres langages, un « hash », une « map » ou un « dictionnaire ».
JSON définit un objet comme suit :
Un objet est un ensemble non ordonné de paires nom/valeur. Un objet commence par une accolade ouvrante
{et se termine par une accolade fermante}. Chaque nom est suivi de deux-points:et les paires nom/valeur sont séparées par une virgule,.
Le nom doit être une string. Un autre mot pour nom est clé.
La valeur peut être de n'importe quel type JSON. Des valeurs différentes dans un même objet peuvent être de types différents, comme dans cet exemple.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
Note qu'il ne doit pas y avoir de virgule après la dernière paire clé-valeur.
Utilise des accolades pour rassembler les paires nom/valeur. Même si les noms doivent être des strings, il n'est pas nécessaire de les mettre entre guillemets s'ils sont de type identifiant (composés de caractères alphanumériques et de tiret bas, et qui ne commencent pas par un chiffre).
{name: "Jane", age: 42}
Il est tout à fait valide d'utiliser des clés qui ne sont pas de type identifiant. Mets-les simplement entre guillemets.
{"first name": "Jane", "last name": "Lopez", age: 42}
Si le nom est le résultat d'une expression, l'expression doit être mise entre parenthèses.
$ echo "Jane" | jq -Rc '{.: 42}'
# verbose error message ...
$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}
On récupère les valeurs d'un objet avec la notation pointée.
{name: "Jane", age: 42} | .age # => 42
Si tu ne peux pas désigner la clé comme un identifiant, utilise la notation par crochets.
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
Pour ajouter une nouvelle paire clé-valeur à un tableau, ou pour mettre à jour la valeur d'une clé existante, utilise l'opérateur d'affectation =, avec une expression d'indice à gauche.
{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
# "name": "Jane",
# "age": 21,
# "sport": "tennis"
# }
L'opérateur + fusionne des objets.
{Richard: 54} + {Jane: 42}
# => {
# "Richard": 54,
# "Jane": 42
# }
Utilise la fonction del pour supprimer une clé.
Elle renvoie l'objet mis à jour.
{name: "Jane", age: 42} | del(.age) # => {"name": "Jane"}
Le paramètre de del est une expression d'indice (en notation pointée ou par crochets) qui se résout en une clé de l'objet.
jq l'appelle une expression de chemin.
Il ne suffit pas de donner une simple string.
{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
Pour tester si l'objet possède une clé, utilise la fonction has.
{name: "Jane", age: 42} as $example
|
($example | has("name")), # => true
($example | has("sport")) # => false
Teste si une clé est dans un objet avec in.
{name: "Jane", age: 42} as $example
|
("name" | in($example)), # => true
("sport" | in($example)) # => false
Utilise la fonction keys pour afficher la liste de toutes les clés.
{name: "Jane", age: 42} | keys # => ["age", "name"]
Note que keys va trier les clés.
Pour récupérer les clés dans l'ordre d'origine, utilise keys_unsorted.
Il n'existe pas de fonction équivalente pour lister toutes les valeurs.
Cependant, le filtre .[] produit les valeurs de l'objet sous forme de flux, et ce flux peut être capturé avec le constructeur de tableau [...].
[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]
La fonction map_values(filter) applique le filtre à chaque valeur de l'objet.
{first: "Jane", last: "Lopez", status: "awesome!"}
| map_values(ascii_upcase)
# => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
Pour itérer sur un objet, il faut d'abord le convertir en un tableau d'objets clé-valeur.
C'est ce que fait la fonction to_entries.
{name: "Jane", age: 42} | to_entries'
# => [
# {
# "key": "name",
# "value": "Jane"
# },
# {
# "key": "age",
# "value": 42
# }
# ]
À ce stade, on peut utiliser les fonctions d'itération sur les tableaux, comme map.
La fonction from_entries fait l'inverse : convertir un tableau d'objets clé-valeur en un objet.
[
{"key":"name", "value":"Jane"},
{"key":"age", "value":42}
] | from_entries # =>{"name": "Jane", "age": 42}
Pour appliquer un filtre à chaque paire clé-valeur d'un objet, utilise la fonction with_entries(filter).
Par exemple, étant donné un objet qui associe un nom à un âge, on peut échanger les clés et les valeurs comme suit.
{"Jane": 42, "Richard": 54}
| with_entries({key: (.value | tostring), value: .key})
produit
{
"42": "Jane",
"54": "Richard"
}
with_entries(filter) équivaut à
to_entries | map(filter) | from_entries
Dans cet exercice, tu vas implémenter un moyen de garder la trace des meilleurs scores du jeu le plus populaire de la salle d'arcade près de chez toi.
Tu as 6 fonctions à implémenter, qui servent principalement à manipuler un objet contenant les meilleurs scores.
Écris une fonction create_score_board qui crée un objet qui sert de tableau des meilleurs scores.
Les clés de cet objet seront les noms des joueurs, et les valeurs, leurs scores.
Pour les besoins des tests, on souhaite inclure directement une entrée dans l'objet.
Cette entrée initiale doit être composée de "The Best Ever" comme nom de joueur et de 1000000 comme score.
create_score_board
# returns an object with one initial entry
Pour ajouter un joueur au tableau des meilleurs scores, implémente la fonction add_player.
Elle prend un tableau des meilleurs scores en entrée et nécessite deux paramètres : le nom du joueur et le score du joueur.
La fonction renvoie le tableau des meilleurs scores avec le nouveau joueur ajouté.
{"José Valim", 486373}
| add_player("Dave Thomas"; 0)
# => {"Dave Thomas": 0, "José Valim": 486373} -- in some order
Si le joueur est déjà sur le tableau, renvoie le tableau inchangé.
Si des joueurs enfreignent les règles de la salle d'arcade, ils sont retirés manuellement du tableau des meilleurs scores.
Implémente remove_player, qui prend un tableau en entrée et un paramètre : le nom du joueur à retirer.
Cette fonction doit supprimer du tableau l'entrée du joueur donné et renvoyer le nouveau tableau.
Si le joueur n'était pas déjà sur le tableau, rien ne doit changer : le tableau doit être renvoyé tel quel.
{"Dave Thomas": 0} | remove_player("Dave Thomas")
# => {}
{"Dave Thomas": 0} | remove_player("Rose Fanaras")
# => {"Dave Thomas": 0}
Si un joueur termine une autre partie à la salle d'arcade, un certain nombre de points s'ajoutent au score précédent du tableau.
Implémente update_score, qui prend un tableau des meilleurs scores en entrée et nécessite deux paramètres : le nom du joueur et le nombre de points à ajouter.
La fonction doit renvoyer le tableau des meilleurs scores une fois la mise à jour effectuée.
{"Freyja Ćirić": 12771000} | update_score("Freyja Ćirić"; 73)
# => {"Freyja Ćirić": 12771073}
Cette fonction doit ajouter le joueur au tableau s'il n'y était pas déjà.
La salle d'arcade tient un tableau des scores séparé le lundi. À la fin de la journée, chaque joueur de ce tableau reçoit 100 points supplémentaires.
Implémente la fonction apply_monday_bonus.
La fonction ajoute les points bonus à chaque joueur inscrit sur ce tableau.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| apply_monday_bonus
# => {"Dave Thomas": 144, "Freyja Ćirić": 639, "José Valim": 365}
Différentes salles d'arcade s'affrontent pour déterminer qui a les meilleurs joueurs. La salle d'arcade avec le score total le plus élevé remporte l'honneur.
Écris une fonction total_score.
Elle prend un tableau des meilleurs scores en entrée et renvoie la somme des scores de tous les joueurs.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| total_score
# => 848
Inscris-toi sur Exercism pour apprendre et maîtriser jq avec 12 concepts75 exercices, et un vrai mentorat humain, le tout gratuitement.