python json load ordereddictionary

python - ¿Puedo hacer que JSON se cargue en un OrderedDict?



load ordereddictionary (6)

Ok, así que puedo usar un OrderedDict en json.dump . Es decir, un OrderedDict se puede usar como entrada para JSON.

¿Pero puede ser usado como una salida? ¿Si es así, cómo? En mi caso, me gustaría load en OrderedDict para poder mantener el orden de las claves en el archivo.

Si no, ¿hay algún tipo de solución?


¿Siempre podría escribir la lista de claves además de descargar el dictado y luego reconstruir OrderedDict iterando a través de la lista?


Además de volcar la lista ordenada de claves junto con el diccionario, otra solución de baja tecnología, que tiene la ventaja de ser explícita, es volcar la lista (ordenada) de pares clave-valor ordered_dict.items() ; La carga es un simple OrderedDict(<list of key-value pairs>) . Esto maneja un diccionario ordenado a pesar del hecho de que JSON no tiene este concepto (los diccionarios JSON no tienen orden).

De hecho, es bueno aprovechar el hecho de que json vuelca el OrderedDict en el orden correcto. Sin embargo, en general es innecesariamente pesado y no necesariamente significativo tener que leer todos los diccionarios JSON como OrderedDict (a través del argumento object_pairs_hook ), por lo que una conversión explícita de solo los diccionarios que deben ordenarse también tiene sentido.


Algunas buenas noticias! Desde la versión 3.6, la implementación de cPython ha preservado el orden de inserción de los diccionarios ( https://mail.python.org/pipermail/python-dev/2016-September/146327.html ). Esto significa que la biblioteca json ahora está conservando el orden de forma predeterminada. Observe la diferencia de comportamiento entre Python 3.5 y 3.6. El código:

import json data = json.loads(''{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}'') print(json.dumps(data, indent=4))

En py3.5 el orden resultante es indefinido:

{ "fiddle": { "bar": 2, "foo": 1 }, "bar": 2, "foo": 1 }

En la implementación cPython de python 3.6:

{ "foo": 1, "bar": 2, "fiddle": { "bar": 2, "foo": 1 } }

La gran noticia es que se ha convertido en una especificación de lenguaje a partir de python 3.7 (a diferencia de un detalle de implementación de cPython 3.6+): https://mail.python.org/pipermail/python-dev/2017-December/151283.html

Entonces, la respuesta a tu pregunta ahora es: ¡actualiza a Python 3.6! :)


El comando de carga normalmente utilizado funcionará si especifica el parámetro object_pairs_hook :

import json from collections import OrderedDict with open(''foo.json'', ''r'') as fp: metrics_types = json.load(fp, object_pairs_hook=OrderedDict)


Sí tu puedes. Al especificar el argumento JSONDecoder en JSONDecoder . De hecho, este es el ejemplo exacto dado en la documentación.

>>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode(''{"foo":1, "bar": 2}'') OrderedDict([(''foo'', 1), (''bar'', 2)]) >>>

Puede pasar este parámetro a json.loads (si no necesita una instancia de Decoder para otros propósitos) así:

>>> import json >>> from collections import OrderedDict >>> data = json.loads(''{"foo":1, "bar": 2}'', object_pairs_hook=OrderedDict) >>> print json.dumps(data, indent=4) { "foo": 1, "bar": 2 } >>>

Usar json.load se hace de la misma manera:

>>> data = json.load(open(''config.json''), object_pairs_hook=OrderedDict)


Versión simple para Python 2.7+

my_ordered_dict = json.loads(json_str, object_pairs_hook=collections.OrderedDict)

O para Python 2.4 a 2.6

import simplejson as json import ordereddict my_ordered_dict = json.loads(json_str, object_pairs_hook=ordereddict.OrderedDict)