Довольно печатные свалки 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"
}
вместо?
Ответы
Ответ 1
Напишите свой собственный сериализатор 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"
}
Ответ 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 говорят, что аргументы по умолчанию: separators=None
- это означает, что используется "по умолчанию" separators=(', ',': ')
). Отметим также, что разделитель запятой не различает пары k/v и элементы списка.
Ответ 3
Возможно, не так эффективно, но рассмотрим более простой случай (несколько проверенный в 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 )
Это может дать вам некоторые идеи, не говоря полностью о написании собственного сериализатора. Я использовал свою собственную любимую технику отступов и жестко закодированную информацию об обеспечении, но вы можете добавлять параметры и передавать их или жестко программировать свои собственные и т.д.
Ответ 4
Это тоже прослушивало меня, я нашел 1 лайнер, которого я почти доволен:
print json.dumps(eval(str(d).replace('[', '"[').replace(']', ']"').replace('(', '"(').replace(')', ')"')), indent=2).replace('\"\\"[', '[').replace(']\\"\"', ']').replace('\"\\"(', '(').replace(')\\"\"', ')')
Чтобы преобразовать все списки или кортежи в строку, используйте json.dumps с отступом для форматирования dict. Затем вам просто нужно удалить кавычки и сделать это!
Примечание. Я преобразую dict в строку, чтобы легко преобразовать все списки/кортежи независимо от того, как вложен файл dict.
PS. Я надеюсь, что полиция Питона не придет за мной за использование eval... (используйте с осторожностью)