2010-11-19 15 views
8

Ho un comando che voglio convertire in JSON usando simplejson.Come assicurarsi che i tasti di un dt piton siano in minuscolo?

Come posso garantire che tutti i tasti del mio dict siano in minuscolo?

{ 
     "DISTANCE": 17.059918745802999, 
     "name": "Foo Bar", 
     "Restaurant": { 
      "name": "Foo Bar", 
      "full_address": { 
       "country": "France", 
       "street": "Foo Bar", 
       "zip_code": "68190", 
       "city": "UNGERSHEIM" 
      }, 
      "phone": "+33.389624300", 
      "longitude": "7.3064454", 
      "latitude": "47.8769091", 
      "id": "538" 
     }, 
     "price": "", 
     "composition": "", 
     "profils": {}, 
     "type_menu": "", 
     "ID": "" 
    }, 

EDIT: Grazie a tutti per dato un'occhiata alla mia domanda, mi dispiace, non ho spiegato nel dettaglio il motivo per cui ho voluto questo. Doveva patteggiare lo JSONEmitter di django-piston.

+2

per assicurare che siano in minuscolo devono essere in minuscolo. Creare un dict con i tasti in minuscolo. –

+0

Cosa intendi con "assicurati"? Hai e hai già dettato e vuoi controllare se tutte le chiavi sono in minuscolo? O convertili tutti in lettere minuscole? O vuoi creare una sorta di dict che consente solo i tasti in minuscolo (quando li inserisci)? – Jordi

+0

Come potete vedere nell'esempio, alcuni dei tasti non sono in minuscolo. Voglio essere sicuro che ogni chiave JSON sia in minuscolo. – Natim

risposta

21
>>> d = {"your": "DATA", "FROM": "above"} 
>>> dict((k.lower(), v) for k, v in d.iteritems()) 
{'from': 'above', 'your': 'DATA'} 
>>> def lower_keys(x): 
... if isinstance(x, list): 
...  return [lower_keys(v) for v in x] 
... elif isinstance(x, dict): 
...  return dict((k.lower(), lower_keys(v)) for k, v in x.iteritems()) 
... else: 
...  return x 
... 
>>> lower_keys({"NESTED": {"ANSWER": 42}}) 
{'nested': {'answer': 42}} 
+0

Ho solo notato che vuoi dettati e elenchi annidati trattati appositamente dalla tua auto-risposta; normalmente lo gestirò a un livello diverso. –

+3

Su python 3 puoi usare la comprensione e non avrai bisogno di 'dict (...)' -> 'd = {k.lower(): v per k, v in d.items()}' – Delblanco

2

Ecco la mia soluzione:

def lower_key(in_dict): 
    if type(in_dict) is dict: 
     out_dict = {} 
     for key, item in in_dict.items(): 
      out_dict[key.lower()] = lower_key(item) 
     return out_dict 
    elif type(in_dict) is list: 
     return [lower_key(obj) for obj in in_dict] 
    else: 
     return in_dict 
+0

Bella soluzione ricorsiva, per gestire il problema dopo "il fatto". – ThomasH

4

Poiché non hai menzionato chiaramente ciò che si vuole fare:

convertire tutti i tasti per le minuscole:

>>> y = dict((k.lower(), v) for k, v in x.iteritems()) 

Controllare chiavi:

>>> for k in x.iterkeys(): 
    if k.islower(): 
     print k, 'True' 
    else: 
     print k, 'False' 
+0

The problema con .iteritems() e .iterkeys() è che non sono ricorsivi. – ThomasH

8

Ecco una soluzione che vieta l'impostazione di una chiave minuscole:

class LowerCaseDict(dict): 
    def __setitem__(self, key, val): 
     if not key.islower(): 
      raise TypeError, "%s key must be lowercase" % key 
     dict.__setitem__(self, key, val) 

ld = LowerCaseDict() 
ld['g']='g' 
+6

Oppure, basta avere '__setitem__' per' dict .__ setitem __ (self, key.lower(), val) '. Il problema con questo approccio in generale è che il costruttore e '.update' non usano __setitem__ - dovrai ovviare a questo, o' LowerCaseDict ({'Foo': 1, 'bar': 2}) ' non agirebbe come previsto (non lo farà in minuscolo per il mio modo o non solleverà un Errore di tipo per il tuo modo). –

+0

Devi anche assicurarti di usare LowerCaseDict per ogni dict annidato. – ThomasH

+0

@Chris Ottimo commento. – ThomasH

2

Se si desidera solo per controllo se sono tutti in minuscolo (il vostro testo, l'utilizzo di "garantire", non è chiaro, ma ho il sospetto che questo non è ciò che si vuole), si può fare in modo compatto che in una sola riga:

all(k.islower() for k in x.iterkeys()) 
2

Ecco una soluzione completa

from requests import CaseInsensitiveDict 

O se si vuole vedere il codice:

class CaseInsensitiveDict(dict): 

    """Basic case insensitive dict with strings only keys.""" 

    proxy = {} 

    def __init__(self, data): 
     self.proxy = dict((k.lower(), k) for k in data) 
     for k in data: 
      self[k] = data[k] 

    def __contains__(self, k): 
     return k.lower() in self.proxy 

    def __delitem__(self, k): 
     key = self.proxy[k.lower()] 
     super(CaseInsensitiveDict, self).__delitem__(key) 
     del self.proxy[k.lower()] 

    def __getitem__(self, k): 
     key = self.proxy[k.lower()] 
     return super(CaseInsensitiveDict, self).__getitem__(key) 

    def get(self, k, default=None): 
     return self[k] if k in self else default 

    def __setitem__(self, k, v): 
     super(CaseInsensitiveDict, self).__setitem__(k, v) 
     self.proxy[k.lower()] = k