2010-11-19 3 views
8

J'ai une dict que je veux convertir en JSON en utilisant simplejson.Comment vous assurer que les clés dict python sont en minuscules?

Comment puis-je m'assurer que toutes les clés de ma dict sont en minuscules?

{ 
     "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: Merci tout avait un coup d'œil à ma question, je suis désolé de ne pas expliquer en détail pourquoi je voulais que cela. C'était pour patcher le JSONEmitter de django-piston.

+2

Pour assurer qu'ils sont en minuscules, ils doivent être en minuscules. Créez une dict avec des minuscules. –

+0

Que voulez-vous dire par "assurer"? Avez-vous et dict existant et voulez-vous vérifier si toutes les touches sont en minuscules? Ou les convertir tous en minuscules? Ou voulez-vous créer une sorte de dict qui n'autorise que les minuscules (en les insérant)? – Jordi

+0

Comme vous pouvez le voir dans l'exemple, certaines des touches ne sont pas en minuscules. Je veux être sûr que chaque clé JSON est en minuscule. – Natim

Répondre

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

J'ai seulement ramassé que vous voulez des dits imbriqués et des listes traitées spécialement à partir de votre réponse personnelle; normalement, je gérerais cela à un niveau différent. –

+3

Sur Python 3 vous pouvez utiliser la compréhension et vous n'aurez pas besoin de 'dict (...)' -> 'd = {k.lower(): v pour k, v dans d.items()}' – Delblanco

2

Voici ma solution:

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

Belle solution récursive, pour gérer le problème après "le fait". – ThomasH

4

Puisque vous ne l'avez pas mentionné clairement ce que vous voulez faire:

Convertir toutes les clés en minuscules:

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

Vérifier touches:

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

problème avec .iteritems() et .iterkeys() est qu'ils ne sont pas récursifs. – ThomasH

8

Voici une solution qui interdit la mise sur une touche minuscule:

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

Ou, juste '__setitem__' fait' dict .__ setitem __ (self, key.lower(), val) '. Le problème avec cette approche en général est que le constructeur et '.update' n'utilisent pas __setitem__ - vous devrez contourner cela, ou' LowerCaseDict ({'Foo': 1, 'bar': 2}) ' n'agirait pas comme prévu (ne le mettra pas en minuscule pour mon chemin ou n'élèvera pas un TypeError pour votre chemin). –

+0

Vous devez également veiller à utiliser également LowerCaseDict pour chaque dict imbriquée. – ThomasH

+0

Grand commentaire @ Chris. – ThomasH

2

Si vous voulez juste vérifier si elles sont minuscules (votre texte, en utilisant « assurer », ne sait pas, mais Je soupçonne que ce n'est pas ce que vous voulez), vous pouvez le faire en une ligne compacte:

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

Voici une solution complète

from requests import CaseInsensitiveDict 

Ou si vous voulez voir le code:

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 
Questions connexes