2014-02-18 5 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', если это строка, у меня больше нет доступа в 'list' (или мне нужно будет разобрать строку в списке, но это позор, чтобы это сделать ...) – 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

Неужели это так сложно? Wow – 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 t полностью писать собственный сериализатор. Я использовал свою собственную любимую технику отступа и жестко 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 говорят арг по умолчанию являются separators=None --that на самом деле означает «использовать значение по умолчанию 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. Тогда вам просто нужно удалить цитаты и сделать это!

Примечание: я конвертирую dict в строку, чтобы легко преобразовать все списки/кортежи независимо от того, как вложен файл dict.

PS. Я надеюсь, что полиция Python не придет за мной за использование eval ... (используйте с осторожностью)

Смежные вопросы