2013-04-14 22 views
5

Sto provando a serializzare i miei oggetti Python in JSON usando json.dumps. Se serializzi un dict usando json.dumps, verrà ovviamente serializzato come un dizionario JSON {..}; se serializzi un list o un tuple, sarà un array JSON.Come convertire Python dict in JSON come lista, se possibile

Voglio sapere se c'è un modo per serializzare facilmente un Python dict come JSON list, se possibile. Da se possibile, intendo se le chiavi partono da 0 e vengono sequenziati, per esempio:

{0:'data',1:'data',2:'data} 

Quanto sopra dovrebbe essere serializzato in JSON come: '{"0": "data", "1": "data", "2": "data"}', ma vorrei che fosse serializzato come ['data','data','data'] poiché i tasti inizia da 0 e sono sequenziati.

Il mio ragionamento per questo è perché ho molti dati JSON che sono serializzati da PHP, dove negli array PHP sono presenti chiavi e se le chiavi sono sequenziate come descritto sopra, PHP json.encode utilizza matrici, se sono immesse in qualsiasi altro modo, sono serializzati come dizionari JSON. Voglio che le mie serializzazioni JSON corrispondano per il mio codice PHP e Python. Sfortunatamente, cambiare il codice PHP non è un'opzione nel mio caso.

Qualche suggerimento? L'unica soluzione che ho trovato è scrivere la mia funzione per verificare e verificare ogni dizionario Python e vedere se può essere prima convertito in list prima di json.dumps.

EDIT: Questo oggetto che sto serializzazione potrebbe essere una list o un dict, così, si potrebbe avere dicts supplementari all'interno di esso, e le liste, e così via (nidificazione). Mi chiedo se ci sia un modo 'semplice' per farlo, altrimenti credo di poter scrivere una soluzione ricorsiva da solo. Ma è sempre meglio usare il codice esistente per evitare altri bug.

+0

Non sono sicuro se 'dict.values ​​()' funzionerà in py3k. Inoltre, FWIW, dicts non è un tipo di dati ordinato, quindi l'ordine della lista serializzata sarà ben definito, ma "arbitrario" anche se si fa 'json.dumps (list (dict.values ​​()))' – mgilson

risposta

3

Non so di una soluzione senza ricorsione ... Anche se è possibile chiamare il convertitore da dentro il metodo della vostra abitudine Encoderencode, sarebbe solo aggiungere inutili complessità .

In [1]: import json 

In [2]: d = {"0": "data0", "1": "data1", "2": {"0": "data0", "1": "data1", "2": "data2"}} 

In [3]: def convert(obj): 
    ...:  if isinstance(obj, (list, tuple)): 
    ...:   return [convert(i) for i in obj] 
    ...:  elif isinstance(obj, dict): 
    ...:   _, values = zip(*sorted(obj.items())) 
    ...:   return convert(values) 
    ...:  return obj 

In [4]: json.dumps(convert(d)) 
Out[4]: '["data0", "data1", ["data0", "data1", "data2"]]' 
2

Si potrebbe convertire il dizionario in una lista di tuple e poi ordinare, come voci del dizionario non necessariamente uscire allo scopo di loro che si desidera:

items = sorted(d.items(), key=lambda item: item[0]) 
values = [item[1] for item in items] 
json_dict = json.dumps(values) 
1

Normalmente si potrebbe sottoclasse json.JSONEncoder a crea il tuo serializzatore JSON personalizzato, ma questo non ti permetterà di sovrascrivere i tipi di oggetti incorporati.

Se si crea il proprio oggetto personalizzato dictlist (o come volete chiamarlo) che non si estende dict o list si dovrebbe essere in grado di eseguire l'override del metodo JSONEncoder.default per creare il proprio personalizzato JSON serializzatore.

Indipendentemente dal fatto che si crea un JSON serializzatore personalizzato o ricorsivamente sostituire i particolari dict istanze con le liste avrete bisogno di una funzione che accetta un dict e restituisce un list o un dict a seconda dei casi.

Ecco un'implementazione:

def convert_to_list(obj): 
    obj_list = [] 
    for i in range(len(obj)): 
     if i not in obj: 
      return obj # Return original dict if not an ordered list 
     obj_list.append(obj[i]) 
    return obj_list