imagen

Disfrutando de la linea de Comandos II, resultados de un Web Service a fichero excel

27.Jun.2018 — Julio

Continuación de Disfrutando de la linea de comandos I

Ya tenemos el resultado del web service obtenido con Curl

Y ahora tenemos que desgranar el resultado devuelto en JSON en ficheros excel. Habrá librerías o utilidades que dado un fichero texto csv lo convierta a formato Excel, pero si queremos ahorrarnos ese paso podemos crear ficheros tsv (separador tabulador) y nombrar a los ficheros con la extensión ".xls". Con ello se consigue que la mayoría de los ordenadores consigan abrir ese fichero en la hoja de cálculo.

Como ya comenté el formato JSON es repetitivo en mi opinión y más complicado de ser tratado por máquinas que un simple csv. Utilizaremos la herramienta jq que es capaz de desgranar cada elemento del JSON y además con una simple opción la formatea a formato @tsv o @csv.


jq vs Go

En Go por ejemplo tenemos la función json.Unmarshal(byte, &structurajson) para descomponer un json (encoding/json). Pero previamente hay que definir la estructura para poder saber cada elemento, y luego además si queremos grabarlo en un fichero csv, hay que utilizar más librerias enconding/csv e ir grabando cada campo. Toca escribir muchas líneas para dado un json crear un fichero csv.

Con jq se puede hacer en una sóla línea.

Bash vs Go

En resumen de lo que llevamos hasta ahora que es utilizar un web service que devuelve un json y crear un fichero excel con el resultado habría que hacer:

en Go:
  • importar librerias de encoding, net/http, io/ioutil, bufio, etc ...
  • crear una función para hacer el GET, con sus headers, petición, resultado en variables...
  • definir structura JSON para el resultado del GET
  • crear fichero de resultado para el csv o texto, lo de siempre, apertura, escrituras, cierres
  • crear funcion de JSON que desengrane los elementos y empezar a escribir en los ficheros

Total, decenas de lineas, con sus

  • if err != nil,
  • conversiones de formatos strconv.Itoa, strconv.FormatFloat, Format("2006-01-02")
  • Flush() de ficheros porque sino se pierden datos
  • de arrays tipo []byte
  • de varias opciones para escribir ficheros csv y al final decantarte por la más simpre de texto bufio.NewWriter porque te da más libertad en cosas que csv.NewWriter no te deja
en Bash:

dos líneas

  • una línea para el curl
  • otra línea para el jq

De acuerdo, mucho he simplificado, y al final mi script en bash tiene más líneas. Pero estoy por asegurar, que he escrito en Python en Go y en Bash el mismo programa que ejecuta

  • 5 web services distintos, encadenados según se van obteniendo resultados de cada uno.
  • con al menos 10 líneas de comentarios al principio de cada uno para explicar lo que se pretende hacer, autor, fecha, versión e índice de cada una de las funciones.
  • luego, dentro de cada programa los comentarios tienen 2 líneas, una en blanco y otra para orientar sobre lo que se va a pretender hacer en las siguientes líneas.
  • cada declaración de variable en su línea. Nada de agrupar varias en la misma línea.
  • una línea en blanco que separa cada función.

y el resultado es que con Bash he escrito 4 veces menos líneas y a la hora de leer es más claro lo que se pretende hacer.

Procuro siempre dejar una buena claridad y visibilidad de las líneas de programa pues a mi mismo me resulta complicado leer un programa que hice yo unos meses atrás. Sí, hay muchos chistes sobre este tema pero es la realidad.

"talk is cheap, show me the code"

No, no voy a subir los fuentes de lo que hice, pero sí dejo dos lineas de ejemplo que aseguré antes que Bash podía hacer todo lo descrito, viendo además todo lo que se está ejecutando por la pantalla:

```
curl -s -o ${output}".json" -H "${header0}" "${link}"  
cat ${output}".json" | jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @tsv' | tee ${output}".xls"  
```

Ala, ya está conseguido el fichero excel ha partir de un GET de un web service. ¿que parece un conjuro de brujería, sobre todo el jq? Sí, también, telita con él. ¿pero acaso cada lenguaje no tiene cosas que escribir de una forma porque sí? ¿acaso cada lenguaje no rompe alguna vez su estilo a la hora de pasar parámetros, llamar a funciones o conversiones y te sorprende y toca memorizar o copiar y pegar de un programa a otro?

Por supuesto, tanto en Go como en Python en el Bash faltan todas las líneas de código de control, para respuestas/ficheros vacíos, excepciones a posibles errores, mensajes al usuario, borrado de ficheros temporales, etc ...

Todas esas líneas que realmente no aportan nada a la función principal de lo que se quiere programar pero que se necesitan como en la vida misma: para intentar paliar lo que te va llegando ...

Tags: bash, jq, curl

Comments? Tweet