web-dev-qa-db-ja.com

JSONダンプをきれいに出力する

このコードを使用して、dictを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"
}

代わりに?

21
Basj

私は jsbeautifier を使用してしまいました:

import jsbeautifier
opts = jsbeautifier.default_options()
opts.indent_size = 2
jsbeautifier.beautify(json.dumps(d), opts)

出力:

{
  "a": "blah",
  "c": [1, 2, 3],
  "b": "foo"
}
10
Allen Z.

独自の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"
}
7
Shan Valleru

別の選択肢は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 の公式ドキュメントでは、デフォルトの引数は_separators=None_であると言っていますが、これは実際には「デフォルトのseparators=(', ',': ')を使用してください。カンマ区切りではk/vペアとリスト要素を区別しないことに注意してください。

4
MarkHu

これもしばらくの間私を悩ませてきました、私は私がほとんど満足している1ライナーを見つけました:

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

それは本質的にすべてのリストまたはタプルを文字列に変換し、インデント付きのjson.dumpsを使用してdictをフォーマットします。次に、引用符を削除して完了です!

注:dictを文字列に変換して、dictがどのようにネストされていても、すべてのリスト/タプルを簡単に変換します。

PS。 Python evalを使用したために警察が私の後に来ないことを願っています...(慎重に使用してください)

0
Tickon

おそらくそれほど効率的ではないかもしれませんが、より単純なケースを検討してください(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 )

これにより、独自のシリアライザーを完全に作成するのではなく、いくつかのアイデアが得られる場合があります。私は自分の好きなインデントテクニックとハードコードされたEnsure_asciiを使用しましたが、パラメーターを追加して渡したり、独自にハードコードしたりできます。

0
Victoria