read ¿Cómo puedo realizar una impresión bonita de JSON en un script de shell(Unix)?




read json in shell script (24)

¿Hay un script de shell (Unix) para formatear JSON en forma legible para el usuario?

Básicamente, quiero que transforme lo siguiente:

{ "foo": "lorem", "bar": "ipsum" }

... en algo como esto:

{
    "foo": "lorem",
    "bar": "ipsum"
}

Así es como lo hago:

curl yourUri | json_pp

Acorta el código y hace el trabajo.


En * nix, leer desde stdin y escribir a stdout funciona mejor:

#!/usr/bin/env python
"""
Convert JSON data to human-readable form.

(Reads from stdin and writes to stdout)
"""

import sys
try:
    import simplejson as json
except:
    import json

print json.dumps(json.loads(sys.stdin.read()), indent=4)
sys.exit(0)

Ponga esto en un archivo (nombré el mío "prettyJSON" después de la respuesta de AnC ) en su PATH y chmod +x it, y listo.


Estoy usando httpie

$ pip install httpie

Y puedes usarlo así.

 $ http PUT localhost:8001/api/v1/ports/my 
 HTTP/1.1 200 OK
 Connection: keep-alive
 Content-Length: 93
 Content-Type: application/json
 Date: Fri, 06 Mar 2015 02:46:41 GMT
 Server: nginx/1.4.6 (Ubuntu)
 X-Powered-By: HHVM/3.5.1

 {
     "data": [], 
     "message": "Failed to manage ports in 'my'. Request body is empty", 
     "success": false
 }

Uso jshon para hacer exactamente lo que estás describiendo. Solo corre:

echo $COMPACTED_JSON_TEXT | jshon

También puede pasar argumentos para transformar los datos JSON.


La versión de PHP, si tiene PHP> = 5.4.

alias prettify_json=php -E '$o = json_decode($argn); print json_encode($o, JSON_PRETTY_PRINT);'
echo '{"a":1,"b":2}' | prettify_json

El JSON Ruby Gem se incluye con un script de shell para pretender JSON:

sudo gem install json
echo '{ "foo": "bar" }' | prettify_json.rb

Descarga de script: gist.github.com/3738968


Gracias a los consejos muy útiles de JF Sebastian, he aquí un script ligeramente mejorado que he encontrado:

#!/usr/bin/python

"""
Convert JSON data to human-readable form.

Usage:
  prettyJSON.py inputFile [outputFile]
"""

import sys
import simplejson as json


def main(args):
    try:
        if args[1] == '-':
            inputFile = sys.stdin
        else:
            inputFile = open(args[1])
        input = json.load(inputFile)
        inputFile.close()
    except IndexError:
        usage()
        return False
    if len(args) < 3:
        print json.dumps(input, sort_keys = False, indent = 4)
    else:
        outputFile = open(args[2], "w")
        json.dump(input, outputFile, sort_keys = False, indent = 4)
        outputFile.close()
    return True


def usage():
    print __doc__


if __name__ == "__main__":
    sys.exit(not main(sys.argv))

Golpe de vainilla

Una secuencia de comandos Bash simple ( grep / awk ) para impresión JSON bonita, sin instalación de terceros:

json_pretty.sh

#/bin/bash

grep -Eo '"[^"]*" *(: *([0-9]*|"[^"]*")[^{}\["]*|,)?|[^"\]\[\}\{]*|\{|\},?|\[|\],?|[0-9 ]*,?' | awk '{if ($0 ~ /^[}\]]/ ) offset-=4; printf "%*c%s\n", offset, " ", $0; if ($0 ~ /^[{\[]/) offset+=4}'

Ejemplos:

1) Leer archivo e impresión bonita en consola.

cat file.json | json_pretty.sh

2) Use con el GIT Bash de Windows de un archivo a otro (basado en UTF8):

cat fileIn.json |sh.exe json_pretty.sh > fileOut.json

jj es súper rápido, puede manejar documentos JSON gigantescos económicamente, no se mete con números JSON válidos y es fácil de usar, por ejemplo

jj -p # for reading from STDIN

o

jj -p -i input.json

Es (2018) todavía bastante nuevo, por lo que tal vez no maneje JSON no válido de la forma que espera, pero es fácil de instalar en las plataformas principales.


Simplemente canalice la salida a jq . .

Ejemplo:

twurl -H ads-api.twitter.com '.......' | jq .

yajl es muy agradable, en mi experiencia. Uso su comando json_reformat para imprimir archivos .json en vim colocando la siguiente línea en mi .vimrc :

autocmd FileType json setlocal equalprg=json_reformat

Utilizo el argumento "espacio" de JSON.stringify para imprimir JSON en JavaScript.

Ejemplos:

// Indent with 4 spaces
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, 4);

// Indent with tabs
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, '\t');

Desde la línea de comandos de Unix con nodejs, especificando json en la línea de comandos:

$ node -e "console.log(JSON.stringify(JSON.parse(process.argv[1]), null, '\t'));" \
  '{"foo":"lorem","bar":"ipsum"}'

Devoluciones:

{
    "foo": "lorem",
    "bar": "ipsum"
}

Desde la línea de comandos de Unix con Node.js, especifique un nombre de archivo que contenga JSON y use una sangría de cuatro espacios:

$ node -e "console.log(JSON.stringify(JSON.parse(require('fs') \
      .readFileSync(process.argv[1])), null, 4));"  filename.json

Usando una pipa:

echo '{"foo": "lorem", "bar": "ipsum"}' | node -e \
"\
 s=process.openStdin();\
 d=[];\
 s.on('data',function(c){\
   d.push(c);\
 });\
 s.on('end',function(){\
   console.log(JSON.stringify(JSON.parse(d.join('')),null,2));\
 });\
"

  1. brew install jq
  2. command + | jq
  3. (Ejemplo: curl localhost:5000/blocks | jq )
  4. ¡Disfrutar!


Pruebe pjson . ¡Tiene colores!

Instalalo con pip :

⚡ pip install pjson

Y luego canaliza cualquier contenido JSON a pjson .


Usualmente solo hago

echo '{"test":1,"test2":2}' | python -mjson.tool

Y para recuperar datos seleccionados (en este caso, el valor de "prueba"):

echo '{"test":1,"test2":2}' | python -c 'import sys,json;data=json.loads(sys.stdin.read()); print data["test"]'

Si los datos JSON están en un archivo:

python -mjson.tool filename.json

Si desea hacerlo todo de una vez con curl en la línea de comandos con un token de autenticación:

curl -X GET -H "Authorization: Token wef4fwef54te4t5teerdfgghrtgdg53" http://testsite/api/ | python -mjson.tool

Escribí una herramienta que tiene uno de los mejores formateadores de "espacios en blanco inteligentes" disponibles. Produce una salida más legible y menos detallada que la mayoría de las otras opciones aquí.

underscore-cli

Así es como se ve el "espacio en blanco inteligente":

Puede que esté un poco sesgado, pero es una herramienta increíble para imprimir y manipular datos JSON desde la línea de comandos. Es muy fácil de usar y tiene una amplia ayuda / documentación en línea de comandos. Es una navaja suiza que utilizo para 1001 tareas pequeñas diferentes que sería sorprendentemente molesto hacer de otra manera.

Último caso de uso: Chrome, consola de desarrollo, pestaña de red, exportar todo como archivo HAR, "cat site.har | subrayado seleccionar '.url' --outfmt text | grep mydomain"; ahora tengo una lista ordenada cronológicamente de todas las recuperaciones de URL realizadas durante la carga del sitio de mi empresa.

La impresión bonita es fácil:

underscore -i data.json print

La misma cosa:

cat data.json | underscore print

Lo mismo, más explícito:

cat data.json | underscore print --outfmt pretty

Esta herramienta es mi proyecto actual de pasión, por lo que si tiene alguna solicitud de características, es muy probable que las aborde.


Echa un vistazo a Jazor . Es un simple analizador JSON de línea de comando escrito en Ruby.

gem install jazor
jazor --help

Con Python 2.6+ simplemente puedes hacer:

echo '{"foo": "lorem", "bar": "ipsum"}' | python -m json.tool

o, si el JSON está en un archivo, puede hacer:

python -m json.tool my_json.json

Si el JSON proviene de una fuente de Internet como una API, puede usar

curl http://my_url/ | python -m json.tool

Para mayor comodidad en todos estos casos puedes hacer un alias:

alias prettyjson='python -m json.tool'

Para aún más comodidad con un poco más de escritura para prepararlo:

prettyjson_s() {
    echo "$1" | python -m json.tool
}

prettyjson_f() {
    python -m json.tool "$1"
}

prettyjson_w() {
    curl "$1" | python -m json.tool
}

Para todos los casos anteriores. Puede poner esto en .bashrc y estará disponible cada vez que esté en shell. prettyjson_s '{"foo": "lorem", "bar": "ipsum"}' como prettyjson_s '{"foo": "lorem", "bar": "ipsum"}' .


$ echo '{ "foo": "lorem", "bar": "ipsum" }' \
> | python -c'import fileinput, json;
> print(json.dumps(json.loads("".join(fileinput.input())),
>                  sort_keys=True, indent=4))'
{
    "bar": "ipsum",
    "foo": "lorem"
}

NOTA: No es la manera de hacerlo.

Lo mismo en Perl:

$ cat json.txt \
> | perl -0007 -MJSON -nE'say to_json(from_json($_, {allow_nonref=>1}), 
>                                     {pretty=>1})'
{
   "bar" : "ipsum",
   "foo" : "lorem"
}

Nota 2: si corres

echo '{ "Düsseldorf": "lorem", "bar": "ipsum" }' \
| python -c'import fileinput, json;
print(json.dumps(json.loads("".join(fileinput.input())),
                 sort_keys=True, indent=4))'

la palabra bien legible se convierte en \ u codificada

{
    "D\u00fcsseldorf": "lorem", 
    "bar": "ipsum"
}

Si el resto de su canalización manejará con gracia unicode y le gustaría que su JSON también sea amigable para el ser humano, simplemente use ensure_ascii=False

echo '{ "Düsseldorf": "lorem", "bar": "ipsum" }' \
| python -c'import fileinput, json;
print json.dumps(json.loads("".join(fileinput.input())),
                 sort_keys=True, indent=4, ensure_ascii=False)'

y obtendrá:

{
    "Düsseldorf": "lorem", 
    "bar": "ipsum"
}


O, con Ruby:

echo '{ "foo": "lorem", "bar": "ipsum" }' | ruby -r json -e 'jj JSON.parse gets'

Si usa npm y Node.js, puede hacer npm install -g json y luego canalizar el comando a través de json . Haz json -h para obtener todas las opciones. También puede extraer campos específicos y colorear la salida con -i .

curl -s http://search.twitter.com/search.json?q=node.js | json

Con Perl, si instala JSON::PP desde CPAN obtendrá el comando json_pp . Robando el example de B Bycroft obtienes:

[[email protected] ~]$ echo '{"foo": "lorem", "bar": "ipsum"}' | json_pp
{
   "bar" : "ipsum",
   "foo" : "lorem"
}

Vale la pena mencionar que json_pp viene preinstalado con Ubuntu 12.04 (al menos) y Debian en /usr/bin/json_pp






pretty-print