Un objeto JSON es, para usar terminología de otros lenguajes, un «hash», un «mapa» o un «diccionario».
JSON define un objeto como:
Un objeto es un conjunto desordenado de pares nombre/valor. Un objeto comienza con
{llave de apertura y termina con}llave de cierre. Cada nombre va seguido de:dos puntos y los pares nombre/valor se separan por,coma.
El nombre debe ser un string. Otra palabra para nombre es clave.
El valor puede ser de cualquier tipo de JSON. Diferentes valores en el mismo objeto pueden ser de diferentes tipos, como en este ejemplo.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
Ten en cuenta que no debe haber una coma después del último par clave-valor.
Usa llaves para agrupar los pares nombre/valor. Aunque los nombres deben ser strings, no necesitan ir entre comillas si los nombres son similares a identificadores (compuestos por caracteres alfanuméricos y guion bajo, y que no comiencen con un dígito).
{name: "Jane", age: 42}
Es válido usar claves que no sean similares a identificadores. Solo ponlas entre comillas.
{"first name": "Jane", "last name": "Lopez", age: 42}
Si el nombre es el resultado de una expresión, la expresión debe ir entre paréntesis.
$ 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}
Un par de casos frecuentes de construcción de objetos tienen una sintaxis abreviada.
Reutilizar pares clave-valor de un objeto de entrada.
$ jq -n '$ENV | {USER: .USER, EDITOR: .EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
$ENV es un objeto que contiene los pares nombre-valor del entorno.
Los pares repetitivos key: .key se pueden escribir simplemente como key
$ jq -n '$ENV | {USER, EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
De manera similar, hay una forma abreviada cuando usas 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"}
Los valores se obtienen de un objeto con notación de punto.
{name: "Jane", age: 42} | .age # => 42
Si no puedes referirte a la clave como un identificador, usa notación de corchetes.
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
Si la clave no está en el objeto, el resultado es null.
{name: "Jane", age: 42} | .sport # => null
Descubrirás que esta es una acción que necesitas hacer una y otra vez al analizar resultados de consultas a API.
Dado un objeto que contiene valores de tipo array u objeto, podemos «encadenar» expresiones de índice.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
| (
.pets[1], # => "fish"
.address.city # => "Springfield"
)
Para agregar un nuevo par clave-valor a un array, o para actualizar el valor de una clave existente, usa el operador de asignación =, con una expresión de índice en el lado izquierdo.
{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
# "name": "Jane",
# "age": 21,
# "sport": "tennis"
# }
El operador + fusiona objetos.
{Richard: 54} + {Jane: 42}
# => {
# "Richard": 54,
# "Jane": 42
# }
Usa la función del para eliminar una clave.
Devuelve el objeto actualizado.
{name: "Jane", age: 42} | del(.age) # => {"name": "Jane"}
El parámetro de del es una expresión de índice (con notación de punto o de corchetes) que resuelve a una clave en el objeto.
jq la llama expresión de ruta.
No basta con dar solo un 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
Para comprobar si el objeto tiene una clave, usa la función has.
{name: "Jane", age: 42} as $example
|
($example | has("name")), # => true
($example | has("sport")) # => false
Comprueba si una clave está en un objeto con in.
{name: "Jane", age: 42} as $example
|
("name" | in($example)), # => true
("sport" | in($example)) # => false
Usa la función keys para generar una lista de todas las claves.
{name: "Jane", age: 42} | keys # => ["age", "name"]
Ten en cuenta que keys ordena las claves.
Para obtener las claves en el orden original, usa keys_unsorted.
No hay una función equivalente para listar todos los valores.
Sin embargo, el filtro .[] genera los valores del objeto como un flujo, y ese flujo se puede capturar con el constructor de array [...].
[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]
La función map_values(filter) aplica el filtro a cada valor del objeto.
{first: "Jane", last: "Lopez", status: "awesome!"}
| map_values(ascii_upcase)
# => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
Para iterar sobre un objeto, primero debemos convertirlo en un array de objetos clave-valor.
La función to_entries hace eso.
{name: "Jane", age: 42} | to_entries
# => [
# {
# "key": "name",
# "value": "Jane"
# },
# {
# "key": "age",
# "value": 42
# }
# ]
En este punto, podemos usar funciones de iteración de arrays, como map.
La función from_entries es la inversa: convierte un array de objetos clave-valor en un objeto.
[
{"key":"name", "value":"Jane"},
{"key":"age", "value":42}
] | from_entries # => {"name": "Jane", "age": 42}
Para aplicar un filtro a cada par clave-valor de un objeto, usa la función with_entries(filter).
Por ejemplo, dado un objeto que asigna un nombre a una edad, las claves y los valores se pueden intercambiar de la siguiente manera.
{"Jane": 42, "Richard": 54}
| with_entries({key: (.value | tostring), value: .key})
produce
{
"42": "Jane",
"54": "Richard"
}
with_entries(filter) es lo mismo que
to_entries | map(filter) | from_entries