2010-05-05 5 views
46

J'ai un problème avec JSON en python. En fait, si j'essaye d'exécuter ce code, python me donne une chaîne JSON triée!Tri JSON en sortie en Python

Par exemple:

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=(',', ':')) 

et c'est la sortie:

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

Comme vous pouvez le voir, j'ai essayé d'utiliser "sort_keys = False" mais rien n'a changé. Comment puis-je arrêter le tri Python mes chaînes JSON?

Répondre

43

Vous stockez vos valeurs dans un python dict qui n'a aucune notion inhérente d'ordre du tout, c'est juste une clé => carte de valeur. Ainsi, vos articles perdent toute commande lorsque vous les placez dans la variable "Valeurs". En fait, la seule façon d'obtenir un ordre déterministe serait d'utiliser "sort_keys = True", ce qui, je suppose, les place dans un ordre alphanumérique. Pourquoi la commande est-elle si importante?

+0

parce que je pense que mon code ne fonctionne pas parce que l'ordre n'est pas le bon. c'est possible? – elledienne

+7

Votre code fonctionne correctement, c'est juste que l'ordre est indéfini. Si vous voulez toujours être cohérent, utilisez "sort_keys = True". –

+0

merci! J'ai résolu !! vous rock;) – elledienne

4

Les clés ne sont pas triées: "profile", "enc_key", "request", "format".

Il semble que vous vouliez qu'ils apparaissent dans le même ordre que vous les avez créés dans le dictionnaire, mais les dictionnaires ne sont pas triés, ils ne se souviennent pas de l'ordre dans lequel vous avez inséré les clés.

Il existe un certain nombre d'implémentations SortedDict que vous pouvez utiliser, mais l'encodeur json ne saura pas comment l'utiliser pour obtenir les clés dans l'ordre souhaité.

6

Si vous spécifiez sort_keys=False, Python imprime simplement les éléments dans l'ordre dans lequel ils apparaissent dans l'objet dict Python sous-jacent. Dans certains cas, cela peut être identique à l'ordre de tri alphanumérique par défaut. Dans votre exemple, les clés ne sont même pas triées comme ça, puisque "format" vient après "request". Peu importe, le paramètre sort_keys est toujours valable, comme en témoigne cet exemple de code:

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

Essayez OrderedDict de la bibliothèque standard 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": "..."}' 

Malheureusement, cette fonctionnalité est New in version 2.7 pour collections

+4

+1 pour fournir une réponse simple mais directe à la question – mloskot

+0

Cette fonctionnalité est disponible pour les anciennes versions de Python en utilisant 'pip install ordereddict', puis en changeant la ligne d'importation en' from orderdict import OrderedDict' comme indiqué sur [cette réponse] (http://stackoverflow.com/a/6852800/892951) (testé sur Python 2.6.6). – chirale

+0

Nice ... mais notez, étonnamment, alors que cela fonctionne pour json 2.0.9 cela ne fonctionne pas (c'est-à-dire l'ordre n'est pas conservé en sérialisation) avec simplejson 2.0.9 (qui est supposé être la version externe de json ?!) . La version de Python est 2.7.3. –

9

Un OrderedDict comme discuté ailleurs est la plus grande partie de la solution à votre problème, et un 'ObjDict' pourrait être encore mieux.

Cependant, si vous avez besoin que l'ordre soit maintenu au chargement, vous aurez également besoin de json.loads() pour charger les valeurs dans un OrderedDict. Pour ce faire, utilisez

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

Sinon, même si le fichier json est en ordre, cet ordre sera perdu lors du chargement.

Peut-être une solution encore meilleure est d'utiliser 'ObjDict' à la place de OrderedDict. Cela nécessite un objdict d'installation de pip. ObjDict maintient toujours l'ordre, comme avec OrderedDict, mais apporte également un support JSON et une meilleure gestion de cet exemple.

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=(',', ':'))