Odpowiedź Mike'a Brennana jest bliska, ale nie ma powodu, aby przemierzać całą strukturę. Jeśli używasz parametru object_hook_pairs
(Python 2.7+):
object_pairs_hook
jest funkcją opcjonalną, która zostanie wywołana z wynikiem dowolnego literału obiektu dekodowanego za pomocą uporządkowanej listy par. Zwrócona wartość object_pairs_hook
zostanie użyta zamiast dict
. Ta funkcja może być wykorzystana do implementacji niestandardowych dekoderów, które opierają się na kolejności dekodowania par klucza i wartości (na przykład collections.OrderedDict
zapamięta kolejność wstawiania). Jeśli object_hook
jest również zdefiniowane, object_pairs_hook
pierwszeństwo ma.
Za jego pomocą otrzymujesz każdy obiekt JSON, dzięki czemu możesz dekodować bez potrzeby rekurencji:
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'}}
Zauważ, że nigdy nie muszę wywoływać haka rekurencyjnie, ponieważ każdy obiekt zostanie przekazany do haka, gdy go użyjesz object_pairs_hook
. Musisz dbać o listy, ale jak widać, obiekt na liście zostanie poprawnie przekonwertowany i nie musisz się powtarzać, aby tak się stało.
EDYCJA: Współpracownik zauważył, że Python2.6 nie ma object_hook_pairs
. Nadal możesz tego używać w Pythonie 2.6, dokonując bardzo małej zmiany. W haku powyżej zmień:
for key, value in pairs:
do
for key, value in pairs.iteritems():
Następnie użyj object_hook
zamiast 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'}}
Wykorzystanie object_pairs_hook
wyników powoduje utworzenie instancji jednego mniejszego słownika dla każdego obiektu w obiekcie JSON, co może być przydatne, jeśli analizujesz ogromny dokument.
str