2014-02-18 247 views
12

我使用此代碼打印出更漂亮一些dict成JSON:漂亮打印JSON轉儲

import json 
d = {'a': 'blah', 'b': 'foo', 'c': [1,2,3]} 
print json.dumps(d, indent = 2, separators=(',', ': ')) 

輸出:

{ 
    "a": "blah", 
    "c": [ 
    1, 
    2, 
    3 
    ], 
    "b": "foo" 
} 

這是一個有點太多(換行符每個列表元素!)。

我應該使用哪種語法有...

{ 
    "a": "blah", 
    "c": [1, 2, 3], 
    "b": "foo" 
} 

呢?

+2

這不完全是您的問題的答案,但是如果您只是在尋找一種簡單易用的數據格式眼睛,你可以試試YAML。對列表和字典等集合有兩種語法,「塊」(其中縮進顯示嵌套)和「流」(括號用於執行該作業)。默認情況下,PyYAML的輸出對不包含任何其他容器的列表和字典使用「流」語法,這聽起來像你想要的漂亮打印。 – Blckknght

+0

謝謝@Blckknght。YAML是成熟的/穩定的/便攜式的,並且可能在未來幾年/未來版本的Python中可用?它會成爲一個標準嗎? (抱歉,所有這些問題;)) – Basj

+0

另一個評論:我想避免轉換成字符串,因爲當我'加載'我的JSON文件到'Dict',如果它是一個字符串,我沒有訪問了到'列表'(或者我需要解析字符串到列表中,但這是一個恥辱,必須這樣做...) – Basj

回答

7

寫自己的JSON序列:

import numpy 

INDENT = 3 
SPACE = " " 
NEWLINE = "\n" 

def to_json(o, level=0): 
    ret = "" 
    if isinstance(o, dict): 
     ret += "{" + NEWLINE 
     comma = "" 
     for k,v in o.iteritems(): 
      ret += comma 
      comma = ",\n" 
      ret += SPACE * INDENT * (level+1) 
      ret += '"' + str(k) + '":' + SPACE 
      ret += to_json(v, level + 1) 

     ret += NEWLINE + SPACE * INDENT * level + "}" 
    elif isinstance(o, basestring): 
     ret += '"' + o + '"' 
    elif isinstance(o, list): 
     ret += "[" + ",".join([to_json(e, level+1) for e in o]) + "]" 
    elif isinstance(o, bool): 
     ret += "true" if o else "false" 
    elif isinstance(o, int): 
     ret += str(o) 
    elif isinstance(o, float): 
     ret += '%.7g' % o 
    elif isinstance(o, numpy.ndarray) and numpy.issubdtype(o.dtype, numpy.integer): 
     ret += "[" + ','.join(map(str, o.flatten().tolist())) + "]" 
    elif isinstance(o, numpy.ndarray) and numpy.issubdtype(o.dtype, numpy.inexact): 
     ret += "[" + ','.join(map(lambda x: '%.7g' % x, o.flatten().tolist())) + "]" 
    else: 
     raise TypeError("Unknown type '%s' for json serialization" % str(type(o))) 
    return ret 

inputJson = {'a': 'blah', 'b': 'foo', 'c': [1,2,3]} 
print to_json(inputJson) 

輸出:

{ 
    "a": "blah", 
    "c": [1,2,3], 
    "b": "foo" 
} 
+0

這真的很複雜嗎?哇 – jpaugh

+0

從我所知道的。 –

+0

我期待大約10行。我猜[Haskell](http://haskell.org)讓我寵壞了! – jpaugh

0

也許不是很有效,但是考慮一個簡單的情況下(在Python 3有些測試,但可能會工作在Python 2):

def dictJSONdumps(obj, levels, indentlevels = 0): 
    import json 
    if isinstance(obj, dict): 
     res = [] 
     for ix in sorted(obj, key=lambda x: str(x)): 
      temp = ' ' * indentlevels + json.dumps(ix, ensure_ascii=False) + ': ' 
      if levels: 
       temp += dictJSONdumps(obj[ ix ], levels-1, indentlevels+1) 
      else: 
       temp += json.dumps(obj[ ix ], ensure_ascii=False) 
      res.append(temp) 
     return '{\n' + ',\n'.join(res) + '\n}' 
    else: 
     return json.dumps(obj, ensure_ascii=False) 

這可能會給你一些想法,shor完全編寫自己的序列化程序。我用我自己最喜歡的縮進技術,硬編碼ensure_ascii,但你可以添加參數,並通過他們,或硬編碼你自己的,等

2

另一種方法是print json.dumps(d, indent = None, separators=(',\n', ': '))

輸出將是:

{"a": "blah", 
"c": [1, 
2, 
3], 
"b": "foo"} 

需要注意的是,雖然在https://docs.python.org/2.7/library/json.html#basic-usage官方文件說默認ARG遊戲separators=None凹口 - 實際上是指「的separators=(', ',': ')使用默認值)。還要注意的是逗號分隔符不不是k/v對和列表區分元素。

+0

謝謝,但這並不完全是我們所需要的;我們希望擁有''[1,2,3]'在一行代替 – Basj

+0

對,它並不完美,但與其他怪物相比,它是精益和平均的;)如果我想變得有趣,我會使用https ://pypi.python.org/pypi/jq/ – MarkHu

+0

Tnx代表分隔符,幫助我支持lua的兼容性。在lua中,不允許有任何空間。 – josifoski

0

這已被竊聽我一會還有,我發現了一個1個襯我幾乎高興:

print json.dumps(eval(str(d).replace('[', '"[').replace(']', ']"').replace('(', '"(').replace(')', ')"')), indent=2).replace('\"\\"[', '[').replace(']\\"\"', ']').replace('\"\\"(', '(').replace(')\\"\"', ')') 

,基本上所有列表或元組轉換爲字符串,然後使用與json.dumps縮進來格式化字典。那麼你只需要刪除引號和你的完成!

注意:無論dict如何嵌套,我都將字典轉換爲字符串以輕鬆轉換所有列表/元組。

PS。我希望Python警察不會在我之後使用eval ...(小心使用)