在Python中格式化JSON

在Python中格式化JSON,python,json,python-3.x,Python,Json,Python 3.x,当初始JSON字符串在没有额外空格或换行符的情况下格式化时,将JSON字符串打印为缩进字符串的最简单方法是什么 目前,我正在运行json.loads(),然后在结果上运行json.dumps()和indent=2。这是可行的,但我觉得我把很多计算都浪费掉了 有没有一种更简单或更高效(内置)的方式来漂亮地打印JSON字符串?(同时将其保留为有效的JSON) 示例 import requests import json response = requests.get('http://spam.eg

当初始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"
    ]
}
json.dumps(obj,indent=2)
优于
pprint
,因为:

  • 使用相同的加载方法会更快
  • 它具有相同或相似的简单性
  • 输出将生成有效的JSON,而
    pprint
    不会 pprint\u vs\u 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指出我的错误

    json.dumps(obj,indent=2)
    优于
    pprint
    ,因为:

  • 使用相同的加载方法会更快
  • 它具有相同或相似的简单性
  • 输出将生成有效的JSON,而
    pprint
    不会 pprint\u vs\u 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指出我的错误

    我认为对于一个真正的JSON对象打印,它可能是最好的
    timeit(数字=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
    ,这会丢失另一个答案中提到的
    true
    null
    false
    等有效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
    # }
    

    它的打印效果非常好,毫不奇怪,在
    timeit(number=10000)
    中运行时需要发出一声呜呜声
    16.701202023s
    ,这是
    json.dumps(json.loads())
    的3倍。除非您花一些时间对其进行优化,否则构建您自己的函数来实现这一点可能是不值得的,而且由于缺少
    内置的
    ,因此,您最好持之以恒,因为您的努力很可能会带来递减的回报。

    我认为对于真正的JSON对象打印,这可能是最好的了
    timeit(数字=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
    ,这会丢失另一个答案中提到的
    true
    null
    false
    等有效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
    # }
    

    它的打印效果非常好,毫不奇怪,在
    timeit(number=10000)
    中运行时需要发出一声呜呜声
    16.701202023s
    ,这是
    json.dumps(json.loads())
    的3倍。为了实现这一点,构建自己的函数可能不值得,除非您花一些时间对其进行优化,并且缺少
    内置的
    ,你最好还是持枪,因为你的努力很可能会带来递减的回报。

    你可能会用漂亮的print@SuperStew但是输出是一个格式化的Python对象,而不是JSON(例如,
    True
    vs
    True
    None
    vs
    null
    ),然后格式化并打印,不管怎样。我不认为
    json.load
    json.dumps
    比任何其他方法都要昂贵,例如使用
    pprint
    而不是
    dumps
    。可能更快。@Idlehands,然后OP调用Python对象上的
    json.dump
    ,将其转换为json。整个问题是关于JSON输出的。Python对象的字符串表示形式与JSON不同,尽管两者相似。@WhiteHotLoveTiger-您能为您试图解码的页面类型提供一个可测试的示例吗?链接“”未解析。如果您提供可用的URL,我可以更新我的答案以反映解码HTTP请求的成本print@SuperStew但是输出是一个格式化的Python对象,而不是JSON(例如,
    True
    vs
    True
    None
    vs
    null
    ),然后格式化并打印,不管怎样。我不认为
    json.load
    json.dumps
    比任何其他方法都要昂贵,例如使用
    pprint
    而不是
    dumps
    。可能更快。@Idlehands,然后OP调用Python对象上的
    json.dump
    ,将其转换为json。整个问题是关于JSON输出的。Python对象的字符串表示形式与JSON不同,尽管两者相似。@WhiteHotLoveTiger-您能为您试图解码的页面类型提供一个可测试的示例吗?链接“”未解析。如果您提供了可用的URL,我可以更新我的答案以反映解码HTTP请求的成本。但是这比使用
    json.dumps
    快吗?我对此表示严重怀疑。而且,结果可能不是有效的JSON。啊,好问题,他确实指定了更“高效”的,不是吗。我可能错误地将其解释为更少的代码行。我必须通过配置文件来直接比较效率。代码行甚至不止一行,因为您只是用一个函数调用替换另一个函数调用。如果有的话,您不需要
    indent
    参数,而是