Comment joliment imprimer un fichier JSON?

1060

J'ai un fichier JSON qui est un gâchis que je veux joli print-- quelle est la façon la plus simple de le faire en python? Je sais que PrettyPrint prend un "objet", qui je pense peut être un fichier, mais je ne sais pas comment passer un fichier - simplement utiliser le nom de fichier ne fonctionne pas.

Colleen
la source
9
Essayez d'analyser le JSON en utilisant json.loads()et d'imprimer le dictionnaire résultant. Ou passez simplement à la section Pretty printing de la documentationjson Python pour .
Blender
1
@Blender si vous postez une réponse, je vous en donnerai le crédit ... cela pourrait être fermé en double, car la solution est la même, mais la question est différente, donc peut-être pas.
Colleen
18
pourquoi pas <your_file.js python -mjson.toolcomme dans le lien de @ ed?
jfs
11
Je ne pense pas que ce soit en double car la jolie impression à partir de la ligne de commande n'est pas la même chose que la jolie impression par programme à partir de Python. Voter pour rouvrir.
vitaut

Réponses:

1664

Le jsonmodule implémente déjà une jolie impression de base avec le indentparamètre:

>>> 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
        ]
    }
]

Pour analyser un fichier, utilisez json.load():

with open('filename.txt', 'r') as handle:
    parsed = json.load(handle)
Mixeur
la source
143
Pour une jolie impression simple, cela fonctionne également sans analyse explicite:print json.dumps(your_json_string, indent=4)
Peterino
1
que fait le tiret?
timbram
8
@timbram: c'est le nombre d'espaces à mettre en retrait.
Blender
9
Sans le retrait, vous obtenez juste une seule ligne de texte laid, c'est pourquoi je suis venu ici.
krs013
6
@Peterino J'ai dû analyser la chaîne json en premier: print(json.dumps(json.loads(your_json_string), indent=2))sinon cela m'a juste montré une chaîne échappée
vladkras
310

Vous pouvez le faire sur la ligne de commande:

python3 -m json.tool some.json

(comme déjà mentionné dans les commentaires de la question, merci à @Kai Petzke pour la suggestion python3).

En fait, python n'est pas mon outil préféré en ce qui concerne le traitement json sur la ligne de commande. Pour une jolie impression simple, c'est ok, mais si vous voulez manipuler le json, cela peut devenir trop compliqué. Vous auriez bientôt besoin d'écrire un fichier de script séparé, vous pourriez vous retrouver avec des cartes dont les clés sont u "some-key" (python unicode), ce qui rend la sélection des champs plus difficile et ne va pas vraiment dans le sens de pretty -impression.

Vous pouvez également utiliser jq :

jq . some.json

et vous obtenez des couleurs en prime (et une extensibilité beaucoup plus facile).

Addendum: Il y a une certaine confusion dans les commentaires concernant l'utilisation de jq pour traiter de gros fichiers JSON d'une part, et avoir un très gros programme jq d'autre part. Pour la jolie impression d'un fichier composé d'une seule grande entité JSON, la limitation pratique est la RAM. Pour la jolie impression d'un fichier de 2 Go composé d'un seul tableau de données du monde réel, la «taille maximale de l'ensemble résident» requise pour la jolie impression était de 5 Go (que ce soit en utilisant jq 1.5 ou 1.6). Notez également que jq peut être utilisé depuis Python après pip install jq.

Gismo Ranas
la source
4
JQ est génial mais il y a une limite maximale, donc inutile pour les gros fichiers. (c'est-à-dire explose en manipulant un fichier de 1,15 Mo) github.com/stedolan/jq/issues/1041
Chris McKee
3
oui, mec, définitivement, si vous écrivez des filtres jq avec plus de 10K lignes de code, je pense que vous essayez quelque chose comme aller à mars avec un vélo.
Gismo Ranas
2
lol: D @ gismo-ranas La version json.tool dirigée vers un fichier fonctionne vraiment très bien sur les gros fichiers; et est stupidement rapide. J'aime JQ mais formater quoi que ce soit au-delà d'une petite charge utile (ce que vous pourriez faire dans la plupart des éditeurs de texte) est hors de sa portée :) Ajout aléatoire: json-generator.com est un outil soigné pour faire des données de test
Chris McKee
5
ou tout simplement:jq '' < some.json
fatal_error
2
En fait, je recommande fortement d'utiliser python3 -m json.tool <IN >OUT, car cela conserve l'ordre d'origine des champs dans les dictons JSON. L'interpréteur python version 2 trie les champs par ordre alphabétique croissant, ce qui n'est souvent pas ce que vous voulez.
Kai Petzke du
55

Vous pouvez utiliser l' empreinte du module intégré (https://docs.python.org/3.6/library/pprint.html) .

Comment lire le fichier avec les données json et l'imprimer.

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
la source
4
Le problème avec cela est que pprint utilisera des guillemets simples et doubles de manière interchangeable, mais json ne nécessite que des guillemets doubles, donc votre json imprimé ne pourra plus analyser en tant que json valide.
drevicko
1
Oui, mais c'est uniquement pour sortir un fichier json. Ne pas prendre la sortie et la réécrire dans un fichier.
ikreb
52

Pygmentize + Python json.tool = Jolie impression avec mise en évidence de la syntaxe

Pygmentize est un outil tueur. Regarde ça.

Je combine python json.tool avec pygmentize

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

Voir le lien ci-dessus pour les instructions d'installation de pygmentize.

Une démonstration de ceci est dans l'image ci-dessous:

démo

Shubham Chaudhary
la source
1
Dans votre exemple, cela -gne fonctionne pas réellement;) Étant donné que l'entrée provient de stdin, pygmentize n'est pas en mesure de faire une bonne supposition. Vous devez spécifier explicitement lexer:echo '{"foo": "bar"}' | python -m json.tool | pygmentize -l json
Denis The Menace
1
@DenisTheMenace Cela fonctionnait en 2015 lorsque j'ai créé cet exemple d'image. Il ne semble pas fonctionner maintenant sur mon système également.
Shubham Chaudhary
36

Utilisez cette fonction et ne vous inquiétez pas d'avoir à vous rappeler si votre JSON est un strou dictencore - regardez simplement la jolie impression:

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
la source
15

J'ai écrit une fois une prettyjson()fonction pour produire une sortie agréable à regarder. Vous pouvez récupérer l'implémentation de ce dépôt .

La principale caractéristique de cette fonction est qu'elle essaie de conserver les éléments dict et list dans une seule ligne jusqu'à ce qu'un certain maxlinelengthsoit atteint. Cela produit moins de lignes de JSON, la sortie semble plus compacte et plus facile à lire.

Vous pouvez produire ce type de sortie par exemple:

{
  "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 Dec'19: j'ai placé le code dans un dépôt séparé , corrigé quelques bugs et fait quelques autres ajustements.

Andy
la source
Je considère que ce formateur est le meilleur des suggestions, mérite plus de votes positifs.
thorhunter
13

Pour pouvoir imprimer à partir de la ligne de commande et pouvoir contrôler l'indentation, etc., vous pouvez configurer un alias similaire à celui-ci:

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

Et puis utilisez l'alias de l'une des manières suivantes:

cat myfile.json | jsonpp
jsonpp < myfile.json
VP
la source
11

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

import pprint
pprint.pprint(json)

print() par rapport à 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
la source
pprintne produit pas de document JSON valide.
selurvedu
5

Voici un exemple simple de jolie impression JSON sur la console d'une manière agréable en Python, sans exiger que le JSON soit sur votre ordinateur en tant que fichier 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
la source
J'obtiens le message d'erreur suivant en Python 3: "TypeError: l'objet JSON doit être str, pas 'octets'"
Mr. T
3
def saveJson(date,fileToSave):
    with open(fileToSave, 'w+') as fileToSave:
        json.dump(date, fileToSave, ensure_ascii=True, indent=4, sort_keys=True)

Il fonctionne pour l'afficher ou l'enregistrer dans un fichier.

Pablo Emmanuel De Leo
la source
1

Je pense que c'est mieux d'analyser le json avant, pour éviter les erreurs:

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
la source
1

Vous pouvez essayer pprintjson .


Installation

$ pip3 install pprintjson

Usage

Imprimez JSON à partir d'un fichier à l'aide de la CLI pprintjson.

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

Jolie impression JSON à partir d'un stdin en utilisant la CLI pprintjson.

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

Jolie impression JSON à partir d'une chaîne à l'aide de la CLI pprintjson.

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

Jolie impression JSON à partir d'une chaîne avec un retrait de 1.

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

Imprimez JSON à partir d'une chaîne et enregistrez la sortie dans un fichier output.json.

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

Production

entrez la description de l'image ici

Travis Clarke
la source
0

C'est loin d'être parfait, mais ça fait l'affaire.

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

vous pouvez l'améliorer, ajouter un retrait et ainsi de suite, mais si vous voulez juste pouvoir lire un json plus propre, c'est la voie à suivre.

Francisco Perdomo
la source