La respuesta de Mike Brennan es cercana, pero no hay razón para volver a atravesar toda la estructura. Si usa el object_hook_pairs
parámetro (Python 2.7+):
object_pairs_hook
es una función opcional que se llamará con el resultado de cualquier objeto literal decodificado con una lista ordenada de pares. Se object_pairs_hook
utilizará el valor de retorno de en lugar de dict
. Esta característica se puede utilizar para implementar decodificadores personalizados que se basan en el orden en que se decodifican los pares clave y valor (por ejemplo, collections.OrderedDict
recordará el orden de inserción). Si object_hook
también se define, object_pairs_hook
tiene prioridad.
Con él, recibe cada objeto JSON, por lo que puede hacer la decodificación sin necesidad de recurrencia:
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'}}
Tenga en cuenta que nunca tengo que llamar al gancho de forma recursiva ya que cada objeto será entregado al gancho cuando use el object_pairs_hook
. Debes preocuparte por las listas, pero como puedes ver, un objeto dentro de una lista se convertirá correctamente y no tienes que recurrir para que suceda.
EDITAR: Un compañero de trabajo señaló que Python2.6 no tiene object_hook_pairs
. Todavía puede usar este Python2.6 haciendo un cambio muy pequeño. En el gancho de arriba, cambie:
for key, value in pairs:
a
for key, value in pairs.iteritems():
Luego use en object_hook
lugar de 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'}}
El uso de object_pairs_hook
resultados en un diccionario menos que se instancia para cada objeto en el objeto JSON, que, si estaba analizando un documento enorme, podría valer la pena.
str