场景
在用python的类似httplib的HTTPConnection模拟http客户端发送application/x-www-form-urlencoded格式数据的时候,习惯使用
urllib的url_encode这个方法来转换字典类型值为key-value格式的字符串,但是这个方法的缺陷是对嵌套类型的字典变量执行的结果是不符合规范的:
嵌套类型:
{
‘key1’:[{'key2':'value2'}, {'key3':'value3'}],
'key4':'value5'
}
url_encode之后,结果是不符合规范的
为了改进这种情况,需要对这个方法进行重写. 见如下:
from urllib import quote, quote_plus, _is_unicode
def urlencode(obj_data, result, p_index = None):
if not isinstance(obj_data, dict) and p_index is None:
return None
# deal list type
if isinstance(obj_data, list):
for inner_v in obj_data:
index_key = p_index
if isinstance(inner_v, dict):
# recursively call
urlencode(inner_v, result, index_key)
elif isinstance(inner_v, list):
# recursively call
urlencode(inner_v, result, '%s[]' % index_key)
else:
if _is_unicode(inner_v):
inner_v = inner_v.encode("ASCII","replace")
result.append({p_index:inner_v})
# deal dict type
elif isinstance(obj_data, dict):
for key, value in obj_data.items():
if p_index is None:
index_key = key
else:
index_key = '%s[%s]' %(p_index, key)
if isinstance(value, dict):
# recursively call
urlencode(value, result, index_key)
elif isinstance(value, list):
# recursively call
urlencode(value, result, '%s[]' % index_key)
else:
# deal string similarly value
# encode transfer
if _is_unicode(value):
value = value.encode("ASCII","replace")
result.append({index_key:value})
# call example
def gen_urlforamt_data(obj_data):
"""
format data to url string
:obj_data dict type
"""
result = list()
urlencode(obj_data, result)
url_elm = list()
for one_elm in result:
for key, value in one_elm.items():
encode_elm = '%s=%s' % (quote_plus(key), quote_plus(str(value)))
url_elm.append(encode_elm)
return '&'.join(url_elm)