tags:

views:

115

answers:

3

I'm trying to urlencode an dictionary in python with urllib.urlencode. The problem is, I have to encode an array.

The result needs to be:

criterias%5B%5D=member&criterias%5B%5D=issue
#unquoted: criterias[]=member&criterias[]=issue

But the result I get is:

criterias=%5B%27member%27%2C+%27issue%27%5D
#unquoted: criterias=['member',+'issue']

I have tried several things, but I can't seem to get the right result.

import urllib
criterias = ['member', 'issue']
params = {
    'criterias[]': criterias,
}
print urllib.urlencode(params)

If I use cgi.parse_qs to decode a correct query string, I get this as result:

{'criterias[]': ['member', 'issue']}

But if I encode that result, I get a wrong result back. Is there a way to produce the expected result?

+5  A: 

You can use a list of key-value pairs (tuples):

>>> urllib.urlencode([('criterias[]', 'member'), ('criterias[]', 'issue')])
'criterias%5B%5D=member&criterias%5B%5D=issue'
Lukáš Lalinský
Too bad this is the only way. but it solved the problem.
Ikke
Well, it's very easy to write a function that transforms the dict with lists into a list of tuples.
Lukáš Lalinský
+1  A: 

Listcomp of values:

>>> criterias = ['member', 'issue']
>>> urllib.urlencode([('criterias[]', i) for i in criterias])
'criterias%5B%5D=member&criterias%5B%5D=issue'
>>> 
gimel
A: 

To abstract this out to work for any parameter dictionary and convert it into a list of tuples:

import urllib

def url_encode_params(params={}):
    if not isinstance(params, dict): 
        raise Exception("You must pass in a dictionary!")
    params_list = []
    for k,v in params.items():
        if isinstance(v, list): params_list.extend([(k, x) for x in v])
        else: params_list.append((k, v))
    return urllib.urlencode(params_list)

Which should now work for both the above example as well as a dictionary with some strings and some arrays as values:

criterias = ['member', 'issue']
params = {
    'criterias[]': criterias,
}
url_encode_params(params)
>>'criterias%5B%5D=member&criterias%5B%5D=issue' 
David