Как конвертировать MultiDict во вложенный словарь - PullRequest
10 голосов
/ 30 января 2012

Я хотел бы преобразовать POST из Webob MultiDict во вложенный словарь. Э.Г.

Так из ПОСТА:

'name=Kyle&phone.number=1234&phone.type=home&phone.number=5678&phone.type=work'

мультидикту;

[('name', 'Kyle'), ('phone.number', '1234'), ('phone.type', 'home'), ('phone.number', '5678'), ('phone.type', 'work')]

во вложенный словарь

{'name': 'Kyle',
 'phone': [
  {
    'number': '12345',
    'type': 'home',
  },{
    'number': '5678',
    'type': 'work',
  },

Есть идеи?

EDIT

Я закончил тем, что извлек метод variable_decode из пакета formencode , отправленный Уиллом. Единственное изменение, которое требовалось, - сделать списки явными, например,

'name=Kyle&phone-1.number=1234&phone-1.type=home&phone-2.number=5678&phone-2.type=work'

Что лучше по многим причинам.

Ответы [ 3 ]

10 голосов
/ 30 января 2012

Если у вас установлен formencode или вы можете установить его, посмотрите их модуль переменного кода

1 голос
/ 30 января 2012

Я предпочитаю явный способ решения вашей проблемы:

  1. Разделите элементы, принадлежащие к одной и той же структуре (или dict), в одну группу с тем же именем поля, как

    'name=Kyle&phone1=1234&phone1=home&phone2=5678&phone2=work'
    
  2. Порядок полей в форме гарантирован, поэтому мультидикт будет: ((«имя», «Кайл»), («телефон1», «1234», «дом»), («телефон2», «5678», «работа»))

  3. Тогда код будет выглядеть так:

    def extract(key, values):
        extractor = {
           "name":str,
           "phone":lambda *args:dict(zip(('number', 'type'), args)
        }
        trimed_key = re.match(r"^(\w+)", key).group(1)
        return trimed_key, extractor(trimed_key, *values)
    
    nested_dict = {}
    for i in multidict():
        key, values = i[0], i[1:]
        nested_dict.setdefault(key, [])
        trimed_key, data_wanted = extract(key, values) 
        nested_dict[trimed_key].append(data_wanted)
    
    for key in nested_dict:
        if len(nested_dict[key]) == 1:
           nested_dict[key] = nested_dict[key][0]
    
1 голос
/ 30 января 2012

У меня не было времени протестировать его, и это довольно ограничительно, но, надеюсь, это сработает (я пишу только потому, что прошло много времени с тех пор, как вы отправили вопрос):

>>> def toList(s):
...     answer = []
...     L = s.split("&")
...     for i in L:
...             answer.append(tuple(i.split('=')))
...     return answer

>>> def toDict(L):
...     answer = {}
...     answer[L[0][0]] = L[0][1]
...     for i in L[1:]:
...             pk,sk = L[i][0].split('.')
...             if pk not in answer:
...                     answer[pk] = []
...             if sk not in answer[pk][-1]:
...                     answer[pk][sk] = L[i][1]
...             else:
...                     answer[pk].append({sk:L[i][1]})

Если это не 100%, это должно, по крайней мере, дать вам хорошее начало.

Надеюсь, это поможет

...