2010-05-05 24 views
46

Tengo un problema con JSON en python.clasificación de salida JSON en Python

De hecho, si trato de ejecutar este código, ¡python me da una cadena JSON ordenada!

Por ejemplo:

values = {'profile' : 'testprofile', 
      'format': 'RSA_RC4_Sealed', 
      'enc_key' : base64.b64encode(chiave_da_inviare), 
      'request' : base64.b64encode(data) 
     } 


values_json = json.dumps(values, sort_keys=False, separators=(',', ':')) 

y este es el resultado:

{"profile":"testprofile","enc_key":"GBWo[...]NV6w==","request":"TFl[...]uYw==","format":"RSA_RC4_Sealed"} 

Como se puede ver, he tratado de usar "sort_keys = False" pero nada cambió.

¿Cómo puedo detener la ordenación de Python de mis cadenas JSON?

Respuesta

43

Está almacenando sus valores en una python dict que no tiene la noción inherente de ordenar, es solo un mapa de clave => valor. Por lo tanto, sus artículos pierden todos los pedidos cuando los coloca en la variable "valores".

De hecho, la única manera de obtener un orden determinista sería usar "sort_keys = True", que supongo que los coloca en orden alfanumérico. ¿Por qué el orden es tan importante?

+0

porque creo que mi código no funciona porque el pedido no es el correcto. ¿Es posible? – elledienne

+7

Tu código está funcionando bien, es solo que el orden no está definido. Si quieres ser siempre consistente usa "sort_keys = True". –

+0

gracias! ¡Lo he resuelto! Rock;) – elledienne

4

Las claves no están ordenadas: "perfil", "enc_key", "solicitud", "formato".

Parece que quiere que aparezcan en el mismo orden en que las creó en el diccionario, pero los diccionarios no están ordenados, no recuerdan el orden en que insertó las claves.

Hay una serie de implementaciones SortedDict que puede usar, pero el codificador json no sabrá usarlas para obtener las claves en el orden que desee.

6

Si especifica sort_keys=False, Python simplemente imprimirá los elementos en el orden en que aparecen en el objeto dict de Python subyacente. En algunos casos, esto puede ser igual al orden de clasificación alfanumérico predeterminado. En su ejemplo, las teclas NO están ni siquiera ordenadas de esa manera, ya que "formato" viene después de "solicitud". En cualquier caso, el parámetro sort_keys sigue siendo válido, como lo demuestra este ejemplo de código:

>>> import json 
>>> json.dumps({"a":5, "b":6, "c":7}, sort_keys=False) 
'{"a": 5, "c": 7, "b": 6}' 
82

Trate OrderedDict de la librería estándar collections:

>>> import json 
>>> from collections import OrderedDict 
>>> values = OrderedDict([('profile','testprofile'), 
          ('format', 'RSA_RC4_Sealed'), 
          ('enc_key', '...'), 
          ('request', '...')]) 
>>> json.dumps(values, sort_keys=False) 
'{"profile": "testprofile", "format": "RSA_RC4_Sealed", "enc_key": "...", "request": "..."}' 

Por desgracia, esta característica es New in version 2.7 para collections

+4

+1 para proporcionar una respuesta simple pero directa a la pregunta – mloskot

+0

Esta función está disponible para la versión anterior de Python usando 'pip install ordereddict' y luego cambia la línea de importación a' from ordereddict import OrderedDict' como se indica en [esta respuesta] (http://stackoverflow.com/a/6852800/892951) (probado en Python 2.6.6). – chirale

+0

Niza ... pero tenga en cuenta, sorprendentemente, mientras esto funciona para json 2.0.9 no funciona (es decir, el orden no se conserva en la serialización) con simplejson 2.0.9 (que supuestamente es simplemente la versión instalada externamente de json ?!) . La versión de Python es 2.7.3. –

9

Un OrderedDict como se discutió en otra parte es la mayor parte de la solución a su problema, y ​​un 'ObjDict' podría ser incluso mejor.

Sin embargo, si necesita que se mantenga el orden de carga, también necesitará json.loads() para cargar los valores en un OrderedDict. Para hacer esto use

from collections import OrderedDict 
values=json.loads(jsontext,object_pairs_hook=OrderedDict) 

De lo contrario, aunque el archivo json estará en orden, esa orden se perderá cuando se cargue.

Quizás una solución aún mejor es usar 'ObjDict' en lugar de OrderedDict. Esto requiere un objdict de instalación de pip. ObjDict todavía mantiene el orden, al igual que con OrderedDict, pero también brinda compatibilidad con JSON y un mejor manejo de este ejemplo.

from objdict import ObjDict 
values = ObjDict("""{"profile" : "testprofile", 
     "format": "RSA_RC4_Sealed" }""") 
values.enc_key = base64.b64encode(chiave_da_inviare) 
values.request = base64.b64encode(data) 

values_json = values.dumps(separators=(',', ':'))