用Python格式化JSON

时间:2018-11-06 15:54:15

标签: python json python-3.x

在格式化初始JSON字符串而没有多余空格或换行符的情况下,将JSON字符串漂亮地打印为带有缩进的字符串的最简单方法是什么?

目前,我正在运行json.loads(),然后在结果上运行json.dumps()indent=2。这行得通,但感觉就像是我在花很多精力在计算上。

是否有更简单或更有效的(内置)方式来漂亮地打印JSON字符串? (同时将其保留为有效JSON)

示例

import requests
import json

response = requests.get('http://spam.eggs/breakfast')
one_line_json = response.content.decode('utf-8')
pretty_json = json.dumps(json.loads(response.content), indent=2)

print(f'Original: {one_line_json}')
print(f'Pretty: {pretty_json}')

输出:

Original: {"breakfast": ["spam", "spam", "eggs"]}
Pretty: {
  "breakfast": [
    "spam", 
    "spam", 
    "eggs"
    ]
}

2 个答案:

答案 0 :(得分:3)

json.dumps(obj, indent=2)pprint更好,因为:

  1. 使用相同的加载方法,速度更快。
  2. 它具有相同或相似的简单性。
  3. 输出将生成有效的JSON,而pprint不会。

pprint_vs_dumps.py

import cProfile
import json
import pprint
from urllib.request import urlopen


def custom_pretty_print():
    url_to_read = "https://www.cbcmusic.ca/Component/Playlog/GetPlaylog?stationId=96&date=2018-11-05"
    with urlopen(url_to_read) as resp:
        pretty_json = json.dumps(json.load(resp), indent=2)
    print(f'Pretty: {pretty_json}')


def pprint_json():
    url_to_read = "https://www.cbcmusic.ca/Component/Playlog/GetPlaylog?stationId=96&date=2018-11-05"
    with urlopen(url_to_read) as resp:
        info = json.load(resp)
    pprint.pprint(info)


cProfile.run('custom_pretty_print()')
>>> 71027 function calls (42309 primitive calls) in 0.084 seconds

cProfile.run('pprint_json()')
>>>164241 function calls (140121 primitive calls) in 0.208 seconds

感谢@tobias_k指出我的错误。

答案 1 :(得分:2)

我认为对于真正的JSON对象打印来说,它可能和它一样好。 timeit(number=10000)花费了大约5.659214497s

import json
d = {   
        'breakfast': [
            'spam', 'spam', 'eggs', 
            {
                'another': 'level', 
                'nested': [
                    {'a':'b'}, 
                    {'c':'d'}
                ]
            }
        ], 
        'foo': True,
        'bar': None
    }
s = json.dumps(d)
q = json.dumps(json.loads(s), indent=2)
print(q)

我尝试使用pprint,但实际上它不会打印纯JSON字符串,除非将其转换为Python dict,这会丢失您的truenullfalse等有效的JSON,如其他答案中所述。同样,它不会保留项目出现的顺序,因此,如果顺序对于可读性很重要,那就不好了。

只是为了好玩,我启动了以下功能:

def pretty_json_for_savages(j, indentor='  '):
    ind_lvl = 0
    temp = ''
    for i, c in enumerate(j):
        if c in '{[':
            print(indentor*ind_lvl + temp.strip() + c)
            ind_lvl += 1
            temp = ''
        elif c in '}]':
            print(indentor*ind_lvl + temp.strip() + '\n' + indentor*(ind_lvl-1) + c, end='')
            ind_lvl -= 1
            temp = ''
        elif c in ',':
            print(indentor*(0 if j[i-1] in '{}[]' else ind_lvl) + temp.strip() + c)
            temp = ''
        else:
            temp += c
    print('')

# {
#   "breakfast":[
#     "spam",
#     "spam",
#     "eggs",
#     {
#       "another": "level",
#       "nested":[
#         {
#           "a": "b"
#         },
#         {
#           "c": "d"
#         }        
#       ]      
#     }    
#   ],
#   "foo": true,
#   "bar": null
# }

它打印得还不错,毫不奇怪的是,花了16.701202023s才能在timeit(number=10000)中运行,这是json.dumps(json.loads()) 3倍您。除非花费一些时间对其进行优化,否则构建自己的函数来实现此目标可能不值得,并且由于缺少builtin,最好坚持使用枪支,因为您的努力很可能收益递减。