Continuamos esta serie, explorando más usos de JQ.
Tal como les expliqué anteriormente, jq
es un lenguaje de programación y como tal nos permite realizar varias operaciones poderosas para analizar datos.
En lo que destaca jq es en el procesamiento de archivos en formato JSON. Como gran parte de las API usan este formato como medio para representar los datos, esta herramienta se vuelve muy útil para explorar este tipo de integraciones.
Vamos a combinar curl
, que es una herramienta que nos permite realizar peticiones sobre HTTP, con jq
, para analizar las respuestas, en este caso, de una API REST.
Más adelante pienso explicar en detalle que es una API REST, por ahora, consideren que es un mecanismo que nos permite interactuar contra un servidor usando el protocolo HTTP, de modo que podemos realizar peticiones contra una URL, usando los verbos que define este protocolo. Para efectos de este ejercicio, y para no extendernos mucho, vamos a usar el método GET.
Vamos a usar una API pública y de uso libre, llamada SWAPI, por Star Wars API. Esta nos proporciona información sobre el universo de la saga de películas creadas por George Lucas. Voy a usar esta API porque es sencilla y no requiere registro ni el uso de credenciales.
El endpoint principal para acceder a SWAPI es el siguiente: https://swapi.dev/api/.
Por ejemplo, si quiero listar las naves espaciales que salen en Star Wars simplemente ejecuto curl del siguiente modo:
curl https://swapi.dev/api/starships
La respuesta será algo así:
{"count":36,"next":"https://swapi.dev/api/starships/?page=2","previous":null,"results":[{"name":"CR90 corvette","model":"CR90 corvette","manufacturer":"Corellian Engineering Corporation","cost_in_credits":"3500000","length":"150","max_atmosphering_speed":"950","crew":"30-165","passengers":"600","cargo_capacity":"3000000","consumables":"1 year","hyperdrive_rating":"2.0","MGLT":"60","starship_class":"corvette","pilots":[],"films":...
Solo he copiado los primeros caracteres del resultado, que como pueden apreciar se puede volver bastante difícil de leer.
Acá viene el primer uso de jq
, como una herramienta que permite “embellecer” la salida del comando curl
.
curl https://swapi.dev/api/starships | jq '.'
Acá pasamos la salida del comando curl
a jq
y le pedimos a este que ejecute la instrucción ‘.’
. Noten el empleo de las comillas simples. Esto es muy importante en entornos tipo Unix (Mac o Linux), puesto que el punto tiene un significado especial, no podemos usarlo sin las comillas simples.1 Esta instrucción simplemente se encarga de imprimir el objeto JSON formateado linea por linea, así que las primeras líneas de este comando se ven así:
{
"count": 36,
"next": "https://swapi.dev/api/starships/?page=2",
"previous": null,
"results": [
{
"name": "CR90 corvette",
"model": "CR90 corvette",
"manufacturer": "Corellian Engineering Corporation",
"cost_in_credits": "3500000",
"length": "150",
"max_atmosphering_speed": "950",
"crew": "30-165",
"passengers": "600",
"cargo_capacity": "3000000",
"consumables": "1 year",
"hyperdrive_rating": "2.0",
"MGLT": "60",
"starship_class": "corvette",
"pilots": [],
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/3/",
...
He recortado la salida, por supuesto, para mostrar las primeras líneas. De esto deducimos que las naves son listadas en un arreglo llamado “results
”.
Obtengamos, entonces, los nombres de las naves.
Para esto ejecutamos este comando:
curl https://swapi.dev/api/starships | jq '.results[].name'
El comando ‘.results[].name’
, nos indica que se debe tomar el atributo “results”
y que este es un arreglo, y luego de cada elemento de este arreglo tomaremos el atributo “name”
. El resultado en este caso es lo siguiente:
"CR90 corvette"
"Star Destroyer"
"Sentinel-class landing craft"
"Death Star"
"Millennium Falcon"
"Y-wing"
"X-wing"
"TIE Advanced x1"
"Executor"
"Rebel transport"
Si estás atento, habrás notado que el primer comando nos indicaba que hay 36 naves, pero acá solamente vemos 10. La razón es que la API retorna la información de manera paginada, puedes solicitar la información agregando el parámetro page a los requests. Te sugiero como ejercicio que hagas los requests página por página, para obtener los nombres de todas las naves.
Pero, ¿qué pasa si quiero obtener los datos del famoso “Millenium Falcon”?
jq nos permite filtrar con la función select
. Lo que haremos es usar este comando:
curl https://swapi.dev/api/starships | jq '.results[] | select(.name == "Millennium Falcon")'
Fíjate cómo primero seleccionamos el arreglo de resultados con ‘.results[]’
, luego usamos la barra (|
) para indicar que esa selección será filtrada por la expresión que la sigue, en este caso select(.name == “Millennium Falcon”)
.
El resultado es el siguiente:
{
"name": "Millennium Falcon",
"model": "YT-1300 light freighter",
"manufacturer": "Corellian Engineering Corporation",
"cost_in_credits": "100000",
"length": "34.37",
"max_atmosphering_speed": "1050",
"crew": "4",
"passengers": "6",
"cargo_capacity": "100000",
"consumables": "2 months",
"hyperdrive_rating": "0.5",
"MGLT": "75",
"starship_class": "Light freighter",
"pilots": [
"https://swapi.dev/api/people/13/",
"https://swapi.dev/api/people/14/",
"https://swapi.dev/api/people/25/",
"https://swapi.dev/api/people/31/"
],
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/2/",
"https://swapi.dev/api/films/3/"
],
"created": "2014-12-10T16:59:45.094000Z",
"edited": "2014-12-20T21:23:49.880000Z",
"url": "https://swapi.dev/api/starships/10/"
}
Nada mal, eh? Con esto terminamos el artículo de hoy, seguro que ya le ves la utilidad a estos rudimentos. Continuamos la próxima semana.
Aprovecho de hacerles notar que he decidido correr la publicación de esta sección para los miércoles. Si crees que a alguien le puede interesar, recuerda compartir este artículo:
Y si eres nuevo por acá, te invito a suscribirte para recibir nuevas actualizaciones.
En Windows el uso de jq requiere de otras convenciones, los remito a la página oficial de jq para que conozcan las consideraciones especiales para ese sistema operativo: https://jqlang.github.io/jq/manual/