2010-05-05 22 views
46

Ho un problema con JSON in python.Ordinamento uscita JSON in Python

Infatti, se provo a eseguire questo codice, python mi fornisce una stringa JSON ordinata!

Ad esempio:

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

e questo è l'output:

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

Come potete vedere, ho cercato di usare "sort_keys = False", ma nulla è cambiato.

Come posso interrompere l'ordinamento Python delle stringhe JSON?

risposta

43

Stai memorizzando i tuoi valori in un python dict che non ha alcuna nozione inerente di ordinare, è solo una chiave => mappa dei valori. Quindi i tuoi articoli perdono tutti gli ordini quando li inserisci nella variabile "valori".

In effetti, l'unico modo per ottenere un ordinamento deterministico sarebbe utilizzare "sort_keys = True", che presumo li collochi in ordine alfanumerico. Perché l'ordine è così importante?

+0

perché penso che il mio codice non funzioni perché l'ordine non è giusto. È possibile? – elledienne

+7

Il codice funziona correttamente, è solo che l'ordine non è definito. Se vuoi essere sempre coerente usa "sort_keys = True". –

+0

grazie! ho risolto !! si rock;) – elledienne

4

Le chiavi non sono ordinate: "profilo", "enc_key", "richiesta", "formato".

Sembra che si desideri che vengano visualizzati nello stesso ordine in cui sono stati creati nel dizionario, ma i dizionari sono intrinsecamente non ordinati, non ricordano l'ordine in cui sono state inserite le chiavi.

Esistono numerose implementazioni SortedDict che è possibile utilizzare, ma il codificatore json non saprà usarlo per ottenere le chiavi nell'ordine desiderato.

6

Se si specifica sort_keys=False, Python stamperà semplicemente gli articoli in qualsiasi ordine essi compaiano nell'oggetto dict Python sottostante. In alcuni casi questo potrebbe essere lo stesso dell'ordine di ordinamento alfanumerico predefinito. Nel tuo esempio, i tasti NON SONO nemmeno ordinati in questo modo, poiché "format" viene dopo "request". Indipendentemente da ciò, il parametro sort_keys è ancora valida, come evidenziato da questo codice di esempio:

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

Prova OrderedDict dalla libreria 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": "..."}' 

Purtroppo questa funzione è New in version 2.7 per collections

+4

+1 per fornire una risposta semplice ma diretta alla domanda posta – mloskot

+0

Questa funzione è disponibile per la versione precedente di Python usando 'pip install ordereddict' e poi cambia la riga di importazione in' orderedict import OrderedDict' come indicato in [questa risposta] (http://stackoverflow.com/a/6852800/892951) (testato su Python 2.6.6). – chirale

+0

Bello ... ma nota, sorprendentemente, mentre questo funziona per json 2.0.9 non funziona (cioè l'ordine non è conservato in serializzazione) con simplejson 2.0.9 (che si suppone sia solo la versione installata esternamente di json ?!) . La versione di Python è 2.7.3. –

9

Un OrderedDict come discusso altrove è la maggior parte della soluzione al tuo problema, e un 'ObjDict' potrebbe essere ancora migliore.

Tuttavia, se è necessario mantenere l'ordine al caricamento, sarà necessario anche json.loads() per caricare i valori in OrderedDict. Per fare questo utilizzare

In caso contrario, anche se il file JSON sarà in ordine, quell'ordine andrà perso quando caricato.

Forse una soluzione ancora migliore è utilizzare "ObjDict" al posto di OrderedDict. Ciò richiede un objdict di installazione del pip. ObjDict mantiene ancora l'ordine, come OrderedDict, ma offre anche supporto JSON e una migliore gestione di questo esempio.

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