これどこだと通用するの?と思ったので軽く調べる
TL;DR
PHPが言語デフォルトで相互変換でき、Railsだとそれに親しいことができる機能がある。
対象とする表記
下記のようなクエリストリング
http://example.com/home?values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two
URIエンコードしてるから見づらいが、デコードするとこんなクエリ
values[0]=zero&values[1]=one&values[2]=two
添字を指定して配列っぽい記述だけど、配列?みたいな記述
そもそもクエリストリングの仕様に配列の言及があるのか
そもそもとして ?
以降のフォーマットに関してどういう値設計にするかのルールは特に記述されていない
しかし、query 構成要素はしばしば "key=value" の対の形式で識別するための情報を運ぶために使用され、そこで頻繁に使用された値は別の URI の参照なので、時にはそれらの文字をパーセントエンコーディングする事を避けるほうがユーザビリティのためにはよい。 - Uniform Resource Identifier (URI): 一般的構文
とあるように一般論として "key=value" の形式であるぐらいでしかRFC上は語られていない
PHPでの振る舞い
たぶんこれが基準じゃないかと思われるPHP
http_build_query
PHP: http_build_query - Manual
$data = ["values" => ["zero","one","two"]];
echo(http_build_query($data));
とやると
values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two
と出力される
parse_str
parse_str("values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two",$output); var_dump($output);
と戻すと
array(1) { ["values"]=> array(3) { [0]=> string(4) "zero" [1]=> string(3) "one" [2]=> string(3) "two" } }
ちなみに後述するRubyが変換した添字の抜けたkey値が抜けている場合は、先頭から順に0,1,2と添字が振られていく
# values[]=zero&values[]=one&values[]=two # 添字がないケース parse_str("values%5B%5D=zero&values%5B%5D=one&values%5B%5D=two",$output); var_dump($output);
array(1) { ["values"]=> array(3) { [0]=> string(4) "zero" [1]=> string(3) "one" [2]=> string(3) "two" } }
途中で値入れると後続が連番になる。
# 途中に2がはいる # values[]=zero&values[2]=one&values[]=two parse_str("values%5B%5D=zero&values%5B2%5D=one&values%5B%5D=two",$output); var_dump($output);
array(1) { ["values"]=> array(3) { [0]=> string(4) "zero" [2]=> string(3) "one" [3]=> string(3) "two" } }
Railsでの振る舞い
to_query
これも似た動作をする
query_hash = {"values": ["zero","one","two"]} query_hash.to_query # => "values%5B%5D=zero&values%5B%5D=one&values%5B%5D=two"
上のものをデコードすると下記、添字が無い。
values[]=zero&values[]=one&values[]=two
Rack::Utils.parse_nested_query
Rack::Utils.parse_nested_query("values%5B%5D=zero&values%5B%5D=one&values%5B%5D=two") # => {"values"=>["zero", "one", "two"]}
[]
は配列として認識して戻す。
PHPでエンコードしたときの文字列は添字情報がキーとなった連想配列(Hash)になる
Rack::Utils.parse_nested_query("values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two") # => {"values"=>{"0"=>"zero", "1"=>"one", "2"=>"two"}}
Goの振る舞い
.Query()
クエリパースをする機能だが、ネストの配列としては見てくれない
package main import ( "fmt" "log" "net/url" ) func main() { u, err := url.Parse("https://example.org/?values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two") if err != nil { log.Fatal(err) } q := u.Query() fmt.Println(q["values[0]"]) }
"values[0]"
という感じで記述しないと取り出せない
Python3での振る舞い
urllib.parse.parse_qs
PythonでURLのクエリ文字列(パラメータ)を取得・作成・変更 | note.nkmk.me
import urllib.parse convertd_dictionary = urllib.parse.parse_qs("values%5B0%5D=zero&values%5B1%5D=one&values%5B2%5D=two") print(convertd_dictionary) # {'values[0]': ['zero'], 'values[1]': ['one'], 'values[2]': ['two']}
Goと同じく value[0]
という文字列がキーになるので意図とズレる
他の言語
ざっと調べた見た感じよしなに作ってくれる実装はなさそう
- 【Java】 URL の クエリ文字列 を組み立てる方法 【いくつか】 ( その他コンピュータ ) - Kerupani129 Project のブログ - Yahoo!ブログ - Javaだと自力作成の事例が多い