Ответ Майка Бреннана близок, но нет причин пересматривать всю структуру. Если вы используете параметр object_hook_pairs
(Python 2.7+):
object_pairs_hook
является необязательной функцией, которая будет вызываться с результатом любого литерала объекта, декодированного упорядоченным списком пар. Возвращаемое значение object_pairs_hook
будет использоваться вместо dict
. Эта функция может быть использована для реализации пользовательских декодеров, которые полагаются на порядок декодирования пар ключ и значение (например, collections.OrderedDict
запомнят порядок вставки). Если object_hook
также определен, object_pairs_hook
приоритет имеет.
С его помощью вы получаете каждый объект JSON, поэтому вы можете выполнять декодирование без необходимости рекурсии:
def deunicodify_hook(pairs):
new_pairs = []
for key, value in pairs:
if isinstance(value, unicode):
value = value.encode('utf-8')
if isinstance(key, unicode):
key = key.encode('utf-8')
new_pairs.append((key, value))
return dict(new_pairs)
In [52]: open('test.json').read()
Out[52]: '{"1": "hello", "abc": [1, 2, 3], "def": {"hi": "mom"}, "boo": [1, "hi", "moo", {"5": "some"}]}'
In [53]: json.load(open('test.json'))
Out[53]:
{u'1': u'hello',
u'abc': [1, 2, 3],
u'boo': [1, u'hi', u'moo', {u'5': u'some'}],
u'def': {u'hi': u'mom'}}
In [54]: json.load(open('test.json'), object_pairs_hook=deunicodify_hook)
Out[54]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
Обратите внимание, что мне никогда не придется вызывать ловушку рекурсивно, так как каждый объект будет передан ловушке, когда вы используете object_pairs_hook
. Вы должны заботиться о списках, но, как видите, объект в списке будет правильно преобразован, и вам не нужно повторяться, чтобы это произошло.
РЕДАКТИРОВАТЬ: сотрудник отметил, что Python2.6 не имеет object_hook_pairs
. Вы все еще можете использовать это Python2.6, сделав очень небольшое изменение. В крюке выше, измените:
for key, value in pairs:
в
for key, value in pairs.iteritems():
Тогда используйте object_hook
вместо object_pairs_hook
:
In [66]: json.load(open('test.json'), object_hook=deunicodify_hook)
Out[66]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
Использование object_pairs_hook
результатов в одном экземпляре словаря для каждого объекта в объекте JSON, что, если вы анализируете огромный документ, может стоить того.
str