シンプルなkey=valueの形式なら何を使っても同じ結果になるけど、ネストしたデータ構造だと結果が違う。
元々はjQueryのparam()とPythonのurlencodeで結果が違うなーと思って(jQueryはPHPと同じ結果になる)調べてたけど、どっちでもサーバー側では問題なく解釈されるみたい。まあサーバーの実装にもよるだろうけど。。
import requests import urllib def flatten(dictionary, parent_key=None): items = [] for key, value in dictionary.items(): new_key = "{}[{}]".format(str(parent_key), key) if parent_key else key if isinstance(value, dict): items.extend(flatten(value, new_key).items()) elif isinstance(value, list) or isinstance(value, tuple): for k, v in enumerate(value): items.extend(flatten({str(k): v}, new_key).items()) else: items.append((new_key, value)) return dict(items) form_data = { "k1" : "v1", "k2" : { "k2_1" : "v2_1", "k2_2" : "v2_2", }, "k3" : ["v3_1", "v3_2", "v3_3", "v3_4"] } # urlencode print(urllib.parse.urlencode(form_data)) # http_build_query compatible print(urllib.parse.urlencode(flatten(form_data)))
$ python a.py | nkf --url-input k1=v1&k2={'k2_1':+'v2_1',+'k2_2':+'v2_2'}&k3=['v3_1',+'v3_2',+'v3_3',+'v3_4'] k1=v1&k2[k2_1]=v2_1&k2[k2_2]=v2_2&k3[0]=v3_1&k3[1]=v3_2&k3[2]=v3_3&k3[3]=v3_4
jQueryでは
decodeURI($.param(form_data)) "k1=v1&k2[k2_1]=v2_1&k2[k2_2]=v2_2&k3[]=v3_1&k3[]=v3_2&k3[]=v3_3&k3[]=v3_4"
jQueryのparam()は配列のインデックスを入れないの?
PHP環境がないので生のhttp_build_query()がどうなってるのか分からないけど、
とりあえず今回は配列データを使わないので気にしないことにした。