Un objet JSON est, pour reprendre la terminologie d'autres langages, un « hash », une « map » ou un dictionnaire.
JSON définit un objet ainsi :
Un objet est un ensemble non ordonné de paires nom/valeur. Un objet commence par
{(accolade ouvrante) et se termine par}(accolade fermante). Chaque nom est suivi de:(deux-points) et les paires nom/valeur sont séparées par,(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"}
}
Remarque 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, ils n'ont pas besoin d'être entre guillemets s'ils sont de type identifiant (composés de caractères alphanumériques et de tirets bas, et ne commençant pas par un chiffre).
{name: "Jane", age: 42}
Il est valide d'utiliser des clés qui ne sont pas de type identifiant. Il suffit de les mettre entre guillemets.
{"first name": "Jane", "last name": "Lopez", age: 42}
Si le nom est le résultat d'une expression, celle-ci doit être entre parenthèses.
$ 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}
Quelques cas fréquents de construction d'objet disposent d'une syntaxe abrégée.
Réutiliser des paires clé-valeur d'un objet d'entrée.
$ jq -n '$ENV | {USER: .USER, EDITOR: .EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
$ENV est un objet qui contient les paires nom-valeur de l'environnement.
Les paires répétitives key: .key peuvent s'écrire simplement key
$ jq -n '$ENV | {USER, EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
De même, il existe une notation abrégée pour les variables.
$ 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"}
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 avec crochets.
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
Si la clé n'est pas présente dans l'objet, le résultat est null.
{name: "Jane", age: 42} | .sport # => null
Tu découvriras qu'il s'agit d'une action que tu devras répéter encore et encore lorsque tu analyseras les résultats de requêtes API.
Étant donné un objet qui contient des valeurs de type tableau ou objet, on peut « enchaîner » les expressions d'indice.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
| (
.pets[1], # => "fish"
.address.city # => "Springfield"
)
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 les 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 avec crochets) qui désigne une clé de l'objet.
jq l'appelle une expression de chemin.
Donner simplement une string ne suffit pas.
{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 présente dans un objet avec in.
{name: "Jane", age: 42} as $example
|
("name" | in($example)), # => true
("sport" | in($example)) # => false
Utilise la fonction keys pour produire la liste de toutes les clés.
{name: "Jane", age: 42} | keys # => ["age", "name"]
Remarque que keys trie les clés.
Pour récupérer les clés dans leur ordre d'origine, utilise keys_unsorted.
Il n'existe pas de fonction équivalente pour lister toutes les valeurs.
En revanche, 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.
La fonction to_entries s'en charge.
{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 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