将Python的嵌套字典变成一维,以便urlencode

urlencode()编码嵌套字典

Python的urllib.parse提供了urlencode()方法,可以直接将字典转换成URL字符串。
但是使用时发现它只能处理一维字典,转换嵌套字典时就会出错。如下:

from urllib import parse

payload = {"status": 200,
           "body": {"id": 1,
                    "msg": "hello"}
           }
url_str = parse.urlencode(payload)  # 编码成URL字符串
print(url_str)
print(parse.unquote(url_str))       # 恢复成Unicode字符串

其显示为:

status=200&body=%7B%27id%27%3A+1%2C+%27msg%27%3A+%27hello%27%7D
status=200&body={'id':+1,+'msg':+'hello'}

可见urlencode()处理内层字典时会出错。

用PHP生成URL字符串

嵌套字典转换成URL字符串之后应该是什么样子?这里用PHP生成它看看。
PHP的http_build_query()与Python的urlencode()都是采用RFC3986规范。

<?php
$payload = array("status"=> 200,
                 "body" => array("id"=> 1,
                                 "msg"=> "hello")
                );
$url_str = http_build_query($payload, '', '&', PHP_QUERY_RFC3986);
echo $url_str;                  // 编码成URL字符串
echo PHP_EOL;
echo urldecode($url_str);       // 恢复成Unicode字符串
?>

其显示为:

status=200&body%5Bid%5D=1&body%5Bmsg%5D=hello
status=200&body[id]=1&body[msg]=hello

将Python的嵌套字典变成一维,以便urlencode

编写个处理函数,将嵌套的内层字典展开,转换成一维字典,然后再由parse.urlencode()处理。

from urllib import parse


def flat_key(layer):
    """ Example: flat_key(["1","2",3,4]) -> "1[2][3][4]" """
    if len(layer) == 1:
        return layer[0]
    else:
        _list = ["[{}]".format(k) for k in layer[1:]]
        return layer[0] + "".join(_list)


def flat_dict(_dict):
    if not isinstance(_dict, dict):
        raise TypeError("argument must be a dict, not {}".format(type(_dict)))
    def __flat_dict(pre_layer, value):
        result = {}
        for k, v in value.items():
            layer = pre_layer[:]
            layer.append(k)
            if isinstance(v, dict):
                result.update(__flat_dict(layer,v))
            else:
                result[flat_key(layer)] = v
        return result
    return __flat_dict([], _dict)


if __name__=="__main__":
    payload = {"status": 200,
               "body": {"id": 1,
                        "msg": "hello"}
              }

    url_str = parse.urlencode(flat_dict(payload))   # 编码成URL字符串
    print(url_str)
    print(parse.unquote(url_str))                   # 恢复成Unicode字符串

其显示为:

status=200&body%5Bid%5D=1&body%5Bmsg%5D=hello
status=200&body[id]=1&body[msg]=hello

可见生成的URL字符串与PHP相同。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值