La respuesta de Mike Brennan es cercana, pero no hay razón para volver a atravesar toda la estructura. Si usa el object_hook_pairsparámetro (Python 2.7+):
object_pairs_hookes una función opcional que se llamará con el resultado de cualquier objeto literal decodificado con una lista ordenada de pares. Se object_pairs_hookutilizará 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.OrderedDictrecordará el orden de inserción). Si object_hooktambién se define, object_pairs_hooktiene 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_hooklugar 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_hookresultados 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