Un objeto JSON es, usando la terminología de otros lenguajes, un «hash», un «mapa» o un «diccionario».
JSON define un objeto de la siguiente manera:
Un objeto es un conjunto desordenado de pares nombre/valor. Un objeto comienza con la llave izquierda
{y termina con la llave derecha}. Cada nombre va seguido de dos puntos:y los pares nombre/valor están separados por una coma,.
El nombre debe ser un string. Otra palabra para nombre es clave.
El valor puede ser de cualquier tipo JSON. Distintos valores en el mismo objeto pueden ser de tipos distintos, 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 hace falta entrecomillarlos si los nombres son similares a un identificador (compuestos por caracteres alfanuméricos y guion bajo, y que no empiezan con un dígito).
{name: "Jane", age: 42}
Es válido usar claves que no sean similares a un identificador. Solo tienes que entrecomillarlas.
{"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}'
# verbose error message ...
$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}
Los valores se obtienen de un objeto con la notación de punto.
{name: "Jane", age: 42} | .age # => 42
Si no puedes referirte a la clave como un identificador, usa la notación de corchetes.
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
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 del 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 (que usa notación de punto o de corchetes) que se resuelve en una clave del 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 obtener 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 .[] produce los valores del objeto como un flujo, y ese flujo se puede capturar con el constructor de arrays [...].
[{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 asocia un nombre a una edad, las claves y los valores se pueden intercambiar así.
{"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
En este ejercicio vas a implementar una forma de llevar un registro de los puntajes más altos del juego más popular de tu salón de arcade local.
Tienes 6 funciones que implementar, relacionadas en su mayoría con la manipulación de un objeto que contiene los puntajes más altos.
Escribe una función create_score_board que cree un objeto que sirva como tablero de puntajes altos.
Las claves de este objeto serán los nombres de los jugadores y los valores, sus puntajes.
Para fines de prueba, quieres incluir directamente una entrada en el objeto.
Esta entrada inicial debe consistir en "The Best Ever" como nombre del jugador y 1000000 como puntaje.
create_score_board
# returns an object with one initial entry
Para agregar un jugador al tablero de puntajes altos, implementa la función add_player.
Recibe un tablero de puntajes como argumento y necesita dos parámetros: el nombre del jugador y el puntaje del jugador.
La función devuelve el objeto del tablero de puntajes con el nuevo jugador agregado.
{"José Valim", 486373}
| add_player("Dave Thomas"; 0)
# => {"Dave Thomas": 0, "José Valim": 486373} -- in some order
Si el jugador ya está en el tablero, devuelve el tablero sin cambios.
Si un jugador viola las reglas del salón de arcade, se elimina manualmente del tablero de puntajes altos.
Implementa remove_player, que recibe un tablero como argumento y un parámetro: el nombre del jugador que se va a eliminar.
Esta función debe eliminar del tablero la entrada del jugador indicado y devolver el nuevo tablero.
Si el jugador no estaba en el tablero desde un principio, no debe pasarle nada al tablero; debe devolverse tal cual.
{"Dave Thomas": 0} | remove_player("Dave Thomas")
# => {}
{"Dave Thomas": 0} | remove_player("Rose Fanaras")
# => {"Dave Thomas": 0}
Si un jugador termina otra partida en el salón de arcade, se sumará una cierta cantidad de puntos al puntaje anterior del tablero.
Implementa update_score, que recibe un tablero de puntajes como argumento y necesita dos parámetros: el nombre del jugador y la cantidad de puntaje que se va a sumar.
La función debe devolver el tablero de puntajes después de hacer la actualización.
{"Freyja Ćirić": 12771000} | update_score("Freyja Ćirić"; 73)
# => {"Freyja Ćirić": 12771073}
Esta función debe agregar al jugador al tablero si aún no estaba en él.
El salón de arcade lleva un tablero de puntajes aparte los lunes. Al final del día, cada jugador de ese tablero recibe 100 puntos adicionales.
Implementa la función apply_monday_bonus.
La función suma los puntos de bonificación a cada jugador que aparece en ese tablero.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| apply_monday_bonus
# => {"Dave Thomas": 144, "Freyja Ćirić": 639, "José Valim": 365}
Distintos salones de arcade compiten entre sí para determinar quién tiene los mejores jugadores. El arcade con el puntaje total más alto se lleva el honor.
Escribe una función total_score.
Recibe un tablero de puntajes como argumento y devuelve la suma de los puntajes de todos los jugadores.
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| total_score
# => 848
Regístrate en Exercism para aprender y dominar jq con 12 conceptos75 ejercicios y mentoría humana real, todo gratis.