Tratar archivos json en Bash

Cuando implementas scripts en Bash, en ocasiones, mas frecuentemente de lo que puedas pensar, necesitas relacionarte con otras aplicaciones. Y no solo esto, sino que además descargas información de diferentes servicios web. En ocasiones está información viene en formato xml, o en texto plano, o en otros formatos, y en ocasiones viene en formato json. ¿Como tratar con json en Bash?¿Como leer archivos json en Bash?¿Como procesar información json en Bash? Pues precisamente esto es lo que te quiero contar en este artículo, y en particular quiero centrarme en jq.

Indicarte que dependendiendo de lo que quiera extraer, en muchas ocasiones, utilizo herramientas como awk, grep, sed o cut. Sin embargo, dependiendo de la complejidad de la información que quiera extraer de ese archivo, este proceso se puede convertir en algo realmente complejo. Así, es precisamente en estos casos, donde la complejidad del archivo a tratar es elevada, donde tener una herramienta como json es garantía de éxito.

Tratar archivos json en Bash

Tratar archivos json en Bash

jq

jq, tal y como lo define el desarrollador de la aplicación, es un ligero y flexible procesador de json para la línea de comandos.

Comparativamente es como sed pero para el caso en el que tienes que tratar con archivos en formato json. Esta herramienta, te permite trabajar con la misma sencillez y facilidad que lo harías con otras herramientas como, sed, awk o grep.

Una interesante características de esta herramienta, es que está implementada en C pero sin ninguna dependencia. De esta forma, tan solo tienes que descargar el archivo, copiarlo a la máquina donde lo necesites y comenzar a trabajar con el.

Filtrar texto

En resumen, jq es un procesador de texto. Un procesador de texto que toma una entrada y produce una salida. Lo interesante de jq es que viene preparado con un potente conjunto de filtros. Filtros que te ayudarán a extraer determinados campos, a convertir un número en texto, o a realizar otras tareas similares.

Para ver como trabajar con estos filtros, te propongo el siguiente archivo json de ejemplo,

{
  "colors": [
    {
      "color": "black",
      "category": "hue",
      "type": "primary",
      "code": {
        "rgba": [255,255,255,1],
        "hex": "#000"
      }
    },
    {
      "color": "white",
      "category": "value",
      "code": {
        "rgba": [0,0,0,1],
        "hex": "#FFF"
      }
    }
  ]
}

Así, por ejemplo, si quisieras sacar el nombre del primer color, tan solo tienes que utilizar el filtro .colors[0].color. Si quisieras sacar el código hexadecimal, el filtro sería colors[0].code.hex. Sencillo, ¿no te parece?. Desde luego si estás familiarizado con las clases y los objetos esto es realmente sencillo para ti. En otro caso, simplemente tienes que pensar que con cada . estás solicitando una propiedad del elemento superior… no se si con esto te habré aclarado mas las ideas o todo lo contrario.

Si quisieras obtener todos los colores, simplemente tienes que utilizar el mismo filtro que el caso anterior, pero sin indicar el índice, es decir colors[].

Ahora bien, si lo que quieres es un array con el valor color de cada uno de los colores, el filtro que tienes que aplicar es .colors[].color. Esto te devolverá lo siguiente,

"black"
"white"

Es posible aplicar varios filtros, de una sola vez pero dependiendo de lo que necesites tendrás que utilizar una solución u otra. Así,

  • , utilizando la coma se aplicarán los diferentes filtros, pero de forma secuancial, y los resultados de cada uno de los filtros aplicados se concatenará al resultado final. Por ejemplo, el filtro
.colors[].code.hex,.colors[].color

devuelve,

"#000"
"#FFF"
"black"
"white"
  • | con esta opcinón se aplican cada filtro al resultado de filtrar el anterior. Así por ejemplo, el filtro,
.colors[].code | .hex

devuelve

"#000"
"#FFF"
"#FF0"

Realizando operaciones

Es posible realizar operaciones matemáticas utilizando jq. Así de vuelta al ejemplo que estás utilizando, es posible realizar la siguiente operación, por ejemplo,

.colors[].code.rgba[0]/2+5

Esto te devolverá,

132.5
5

Si quisieras que te devolviera un array, simplemente tienes que cerrar entre corchetes esa operación,

Funciones

Pero no solo esto, y es que resulta que jq te ofrece diferentes funciones para trabajar con los archivos json. Algunas de estas funciones son las siguientes,

  • length te permite conocer el número de elementos de un array, o la longitud de una cadena de texto. Por ejemplo, .colors | length te devolverá 2.
  • keys te devuelve las claves de un objeto. Por ejemplo, .colors[0] | keys, te mostrará el siguiente resultado,
[
  "category",
  "code",
  "color",
  "type"
]
  • la función has te permite comprobar si un determinado objeto tiene una clave concreta. Por ejemplo, .colors[0] | has("category") te devolverá true.
  • explode convierte una cadena de texto en un array.
  • implode realiza la operación inversa a la anterior.
  • map para cada uno de los elementos de un array te devuelve el resultado de la operación.
  • del elimina una clave
  • any parte de un array y devolverá true si al menos uno de los elementos toma ese valor.
  • all hace lo mismo pero siempre que la condición la cumplan todos los elementos.
  • flaten parte de un array de arrays y lo convierte en un array simple
  • range genera un rango de números.

No solo esto, sino que además jq te proporcina operadores similares a SQL. Eso si, no son muchos, se limita a unos pocos, como pueden ser JOIN o IN. Sin embargo, si te sientes cómodo utilizando este lenguaje, tienes aquí mas opciones.

Condicionales y comparadores

Puedes utilizar diferentes comparadores, así por ejemplo, puedes utilizar ==, !=. Así, en el ejemplo que estás utilizando, puedes probar lo siguiente,

$ jq '.colors[].category=="hue"' example.json 

true
false

Otra opción interesante es utilizar if-then-else. De nuevo si lo pruebas con el ejemplo que te traes entre manos,

jq 'if .colors[].category=="hue" then "buena" else "mala" end' example.json 
"buena"
"mala"

No solo esto, sino que puedes utilizar otros operadores como and, or, not. Incluso tienes la opción de utilizar try-catch para capturar errores.

Y si todo esto te parece poco, también tienes la posibilidad de utilizar expresiones regulares. Simplemente las posibilidades que tienes son brutales. Por esto, te recomiendo que cuando tengas ocasión acudas a la documentación oficial de jq.

Probando jq

Indicarte, que puedes probar directamente el funcionamiento de jq, sin necesidad de instalar nada. Simplemente abre jqplay, en un navegador y comienza a practicar con él. Pero por supuesto, también puedes probar esta herramienta directamente instalando la aplicación en tu equipo. Esto es algo tan sencillo como ejectuar sudo apt install jq.


Más información,

Imagen de portada de Maarten van den Heuvel en Unsplash

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *