Mateus Felipe
Mateus Felipe

Reputation: 1171

Encode URL with nested dictionaries

I am using an API that doesn't accept JSON in the requests' bodies. It uses x-www-form-urlencoded.

Thus, if I have to send this dict:

{
    'a': 1,
    'b': 2,
    'c': {
        'k': 3,
        'v': 4,
        'l': {
            'p': 5,
            'q': 6,
        },
    },
}

It have to be encoded like this:

a=1
b=2
c[k]=3
c[v]=4
c[l][p]=5
c[l][q]=6

However, urllib.parse.urlencode won't parse the dict this way. Instead it's going to encode c content literally and put within it (c={encodeddict}).

I tried to implement some encoder like this by myself, but I couldn't get to deal with multiple nested dicts. I only managed to encode 1-level dicts (like c[k]=3), but not recursively to the last level (c[l][p]=5, for example).

What is the best way to achieve this kind of encoding in Python 3?

Upvotes: 4

Views: 1657

Answers (1)

ran632
ran632

Reputation: 1209

Using recursion:

pass your dict to dict_to_urlencoded(), and it'll return encoded format string based on your description. (unsorted)

def dict_to_urlencoded(d):
    return kv_translation(d, "", "")


def kv_translation(d, line, final_str):
    for key, value in d.items():
        key_str = key if not line else "[{}]".format(key)
        if type(value) is dict:
            final_str = kv_translation(d[key], line + key_str, final_str)
        elif type(value) is list:
            key_str += '[]'
        elif type(value) is not str:
            value = str(value)
        else:
            final_str = "{}{}{}={}\n".format(final_str, line, key_str, urlencode(value))

return final_str

Upvotes: 3

Related Questions