2010-11-19 5 views
8

У меня есть dict, который я хочу преобразовать в JSON, используя simplejson.Как обеспечить, чтобы клавиши python dict были строчными?

Как я могу гарантировать, что все ключи моего dict строчные?

{ 
     "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: Спасибо всем, чтобы было смотреть на мой вопрос, я жалею, что не объяснить подробные почему я этого хотел. Это было исправление JSONEmitter от django-piston.

+2

Чтобы гарантировать, что они в нижнем регистре, они должны быть в нижнем регистре. Создайте файл с строчными клавишами. –

+0

Что вы подразумеваете под "гарантией"? У вас есть и существующий dict, и вы хотите проверить, все ли клавиши в нижнем регистре? Или преобразовать их все в нижний регистр? Или вы хотите создать своего рода диктовку, которая допускает только клавиши нижнего регистра (при их вставке)? – Jordi

+0

Как вы можете видеть в примере, некоторые из них не строчные. Я хочу быть уверенным, что каждый ключ JSON имеет нижний регистр. – Natim

ответ

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

Я только подобрал, что вы хотите, чтобы вложенные дикты и списки обрабатывались специально из вашего самообслуживания; обычно я бы справился с этим на другом уровне. –

+3

На python 3 вы можете использовать понимание и не нуждаетесь в 'dict (...)' -> 'd = {k.lower(): v для k, v в d.items()}' – Delblanco

2

Вот мое решение:

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

Хорошее рекурсивное решение, чтобы справиться с проблемой после «факта». – ThomasH

4

Поскольку вы не упомянули ясно, что вы хотите сделать:

Преобразовать все ключи к нижнему регистру:

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

Проверить ключи:

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

проблема с .iteritems() и .iterkeys() заключается в том, что они не являются рекурсивными. – ThomasH

8

Вот решение, которое запрещает установление нижнего регистра ключа:

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

Или просто '__setitem__' do' dict .__ setitem __ (self, key.lower(), val) '. Проблема с этим подходом в общем состоит в том, что конструктор и '.update' не используют __setitem__ - вам нужно будет обойти это, или' LowerCaseDict ({'Foo': 1, 'bar': 2}) ' не будет действовать так, как ожидалось (не будет загладить это для моего пути или не будет поднимать TypeError для вашего пути). –

+0

Вы также должны также использовать LowerCaseDict для каждого вложенного dict. – ThomasH

+0

@ Chris Отличный комментарий. – ThomasH

2

Если вы просто хотите проверки, если они все в нижнем регистре (ваша формулировка, используя «обеспечить», пока не ясно, но Я подозреваю, что это не то, что вы хотите), вы можете сделать это компактно в одной строке:

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

Вот полное решение

from requests import CaseInsensitiveDict 

Или, если вы хотите увидеть код:

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