¿Cómo imprimir un archivo JSON?

1060

Tengo un archivo JSON que es un desastre que quiero imprimir. ¿Cuál es la forma más fácil de hacer esto en Python? Sé que PrettyPrint toma un "objeto", que creo que puede ser un archivo, pero no sé cómo pasar un archivo; solo usar el nombre de archivo no funciona.

Muchacha
fuente
99
Intente analizar el JSON usando json.loads()e imprima bonito ese diccionario resultante. O simplemente salte a la sección de Impresión bonita de la documentación dejson Python .
Blender
1
@Blender si publicas una respuesta, te daré crédito ... esto podría cerrarse como un duplicado, porque la solución es la misma, pero la pregunta es diferente, así que quizás no.
Colleen
18
¿Por qué no <your_file.js python -mjson.toolcomo en el enlace de @ ed?
jfs
11
No creo que sea duplicado porque la impresión bonita desde la línea de comandos no es lo mismo que la impresión bonita desde Python mediante programación. Votación para reabrir.
vitaut

Respuestas:

1664

El jsonmódulo ya implementa algunas impresiones bonitas básicas con el indentparámetro:

>>> import json
>>>
>>> your_json = '["foo", {"bar":["baz", null, 1.0, 2]}]'
>>> parsed = json.loads(your_json)
>>> print(json.dumps(parsed, indent=4, sort_keys=True))
[
    "foo", 
    {
        "bar": [
            "baz", 
            null, 
            1.0, 
            2
        ]
    }
]

Para analizar un archivo, use json.load():

with open('filename.txt', 'r') as handle:
    parsed = json.load(handle)
Licuadora
fuente
143
Para una impresión bonita, esto también funciona sin un análisis explícito:print json.dumps(your_json_string, indent=4)
Peterino
1
¿Qué hace el guión?
timbram
8
@timbram: es el número de espacios para sangrar.
Blender
99
Sin la sangría, solo obtienes una sola línea de texto feo, por eso vine aquí.
krs013
66
@Peterino Tuve que analizar la cadena json primero: de lo print(json.dumps(json.loads(your_json_string), indent=2))contrario, solo me mostró una cadena escapada
vladkras
310

Puede hacer esto en la línea de comando:

python3 -m json.tool some.json

(como ya se mencionó en los comentarios a la pregunta, gracias a @Kai Petzke por la sugerencia de python3).

En realidad, Python no es mi herramienta favorita en lo que respecta al procesamiento json en la línea de comandos. Por simple impresión bonita está bien, pero si desea manipular el json puede complicarse demasiado. Pronto necesitaría escribir un archivo de script por separado, podría terminar con mapas cuyas claves son u "alguna clave" (python unicode), lo que hace que la selección de campos sea más difícil y realmente no va en la dirección bonita -impresión.

También puedes usar jq :

jq . some.json

y obtienes colores como bonificación (y una extensibilidad mucho más fácil).

Anexo: Existe cierta confusión en los comentarios sobre el uso de jq para procesar archivos JSON grandes por un lado, y tener un programa jq muy grande por el otro. Para la impresión bonita de un archivo que consta de una sola entidad JSON grande, la limitación práctica es la RAM. Para la impresión bonita de un archivo de 2 GB que consta de una sola matriz de datos del mundo real, el "tamaño máximo establecido para residentes" requerido para la impresión bonita era de 5 GB (ya sea usando jq 1.5 o 1.6). Tenga en cuenta también que jq se puede usar desde Python después pip install jq.

Gismo Ranas
fuente
44
JQ es genial, pero hay un límite máximo, por lo que es inútil para archivos grandes. (es decir, explota manejando un archivo de 1.15mb
Chris McKee
3
Sí, hombre, definitivamente, si estás escribiendo filtros jq con más de 10K líneas de código, creo que estás intentando algo como ir a Marte con una bicicleta.
Gismo Ranas
2
lol: D @ gismo-ranas La versión json.tool canalizada a un archivo funciona muy bien en archivos grandes; y es estúpidamente rápido Me gusta JQ, pero formatear cualquier cosa más allá de una pequeña carga útil (que podría hacer en la mayoría de los editores de texto) está más allá de su alcance :) Adición aleatoria: json-generator.com es una herramienta ordenada para hacer datos de prueba
Chris McKee
55
o simplemente:jq '' < some.json
fatal_error
2
En realidad, recomiendo usarlo python3 -m json.tool <IN >OUT, ya que esto mantiene el orden original de los campos en los dictados JSON. La versión 2 del intérprete de Python clasifica los campos en orden alfabético ascendente, que a menudo no es lo que desea.
Kai Petzke
55

Puede usar el módulo integrado pprint (https://docs.python.org/3.6/library/pprint.html) .

Cómo puede leer el archivo con datos json e imprimirlo.

import json
import pprint

json_data = None
with open('filename.txt', 'r') as f:
    data = f.read()
    json_data = json.loads(data)

pprint.pprint(json_data)
ikreb
fuente
44
El problema con esto es que pprint utilizará comillas simples y dobles de manera intercambiable, pero json solo requiere comillas dobles, por lo que es posible que su json impreso ya no se analice como json válido.
drevicko
1
Sí, pero es solo para generar un archivo json. No tomar la salida y volver a escribirla en un archivo.
ikreb
52

Pygmentize + Python json.tool = Impresión bonita con resaltado de sintaxis

Pygmentize es una herramienta asesina. Mira esto.

Combino python json.tool con pygmentize

echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json

Consulte el enlace de arriba para obtener instrucciones de instalación de pygmentize.

Una demostración de esto está en la imagen a continuación:

manifestación

Shubham Chaudhary
fuente
1
En su ejemplo, en -grealidad no funciona;) Dado que la entrada proviene de stdin, pygmentize no puede hacer una buena suposición. Debe especificar lexer explícitamente:echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json
Denis The Menace
1
@DenisTheMenace Solía ​​funcionar en 2015 cuando creé esta imagen de ejemplo. No parece estar funcionando ahora también en mi sistema.
Shubham Chaudhary
36

Use esta función y no se preocupe por tener que recordar si su JSON es uno stro dictmás, solo mire la bonita impresión:

import json

def pp_json(json_thing, sort=True, indents=4):
    if type(json_thing) is str:
        print(json.dumps(json.loads(json_thing), sort_keys=sort, indent=indents))
    else:
        print(json.dumps(json_thing, sort_keys=sort, indent=indents))
    return None

pp_json(your_json_string_or_dict)
zelusp
fuente
15

Una vez escribí una prettyjson()función para producir una salida bonita. Puede obtener la implementación de este repositorio .

La característica principal de esta función es que trata de mantener el dict y enumerar los elementos en una línea hasta que maxlinelengthse alcanza cierto . Esto produce menos líneas de JSON, la salida se ve más compacta y más fácil de leer.

Puede producir este tipo de salida, por ejemplo:

{
  "grid": {"port": "COM5"},
  "policy": {
    "movingaverage": 5,
    "hysteresis": 5,
    "fan1": {
      "name": "CPU",
      "signal": "cpu",
      "mode": "auto",
      "speed": 100,
      "curve": [[0, 75], [50, 75], [75, 100]]
    }
}

UPD Dic'19: coloqué el código en un repositorio separado , corregí algunos errores e hice algunos otros ajustes.

Andy
fuente
Considero que este formateador es el mejor de los sugeridos, merece más votos a favor.
thorhunter
13

Para poder imprimir desde la línea de comandos y poder tener control sobre la sangría, etc., puede configurar un alias similar a este:

alias jsonpp="python -c 'import sys, json; print json.dumps(json.load(sys.stdin), sort_keys=True, indent=2)'"

Y luego use el alias de una de estas maneras:

cat myfile.json | jsonpp
jsonpp < myfile.json
VP
fuente
11

Utilice pprint: https://docs.python.org/3.6/library/pprint.html

import pprint
pprint.pprint(json)

print() comparado con pprint.pprint()

print(json)
{'feed': {'title': 'W3Schools Home Page', 'title_detail': {'type': 'text/plain', 'language': None, 'base': '', 'value': 'W3Schools Home Page'}, 'links': [{'rel': 'alternate', 'type': 'text/html', 'href': 'https://www.w3schools.com'}], 'link': 'https://www.w3schools.com', 'subtitle': 'Free web building tutorials', 'subtitle_detail': {'type': 'text/html', 'language': None, 'base': '', 'value': 'Free web building tutorials'}}, 'entries': [], 'bozo': 0, 'encoding': 'utf-8', 'version': 'rss20', 'namespaces': {}}

pprint.pprint(json)
{'bozo': 0,
 'encoding': 'utf-8',
 'entries': [],
 'feed': {'link': 'https://www.w3schools.com',
          'links': [{'href': 'https://www.w3schools.com',
                     'rel': 'alternate',
                     'type': 'text/html'}],
          'subtitle': 'Free web building tutorials',
          'subtitle_detail': {'base': '',
                              'language': None,
                              'type': 'text/html',
                              'value': 'Free web building tutorials'},
          'title': 'W3Schools Home Page',
          'title_detail': {'base': '',
                           'language': None,
                           'type': 'text/plain',
                           'value': 'W3Schools Home Page'}},
 'namespaces': {},
 'version': 'rss20'}
Nakamoto
fuente
pprintno produce un documento JSON válido.
selurvedu
5

Aquí hay un ejemplo simple de impresión bonita de JSON en la consola de una manera agradable en Python, sin requerir que JSON esté en su computadora como un archivo local:

import pprint
import json 
from urllib.request import urlopen # (Only used to get this example)

# Getting a JSON example for this example 
r = urlopen("https://mdn.github.io/fetch-examples/fetch-json/products.json")
text = r.read() 

# To print it
pprint.pprint(json.loads(text))
David Liu
fuente
Recibo el siguiente mensaje de error en Python 3: "TypeError: el objeto JSON debe ser str, no 'bytes'"
Sr. T
3
def saveJson(date,fileToSave):
    with open(fileToSave, 'w+') as fileToSave:
        json.dump(date, fileToSave, ensure_ascii=True, indent=4, sort_keys=True)

Funciona para mostrarlo o guardarlo en un archivo.

Pablo Emmanuel De Leo
fuente
1

Creo que es mejor analizar el json antes, para evitar errores:

def format_response(response):
    try:
        parsed = json.loads(response.text)
    except JSONDecodeError:
        return response.text
    return json.dumps(parsed, ensure_ascii=True, indent=4)
p3quod
fuente
1

Puedes probar pprintjson .


Instalación

$ pip3 install pprintjson

Uso

Imprima JSON desde un archivo usando la CLI de pprintjson.

$ pprintjson "./path/to/file.json"

Imprima JSON desde un stdin usando la CLI de pprintjson.

$ echo '{ "a": 1, "b": "string", "c": true }' | pprintjson

Imprime JSON desde una cadena usando la CLI de pprintjson.

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }'

Imprime JSON desde una cadena con una sangría de 1.

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -i 1

Imprima JSON desde una cadena y guarde la salida en un archivo output.json.

$ pprintjson -c '{ "a": 1, "b": "string", "c": true }' -o ./output.json

Salida

ingrese la descripción de la imagen aquí

Travis Clarke
fuente
0

Está lejos de ser perfecto, pero hace el trabajo.

data = data.replace(',"',',\n"')

puede mejorarlo, agregar sangría, etc., pero si solo desea poder leer un json más limpio, este es el camino a seguir.

Francisco Perdomo
fuente