URL のクエリ文字列を読む・組み立てる

自分で split() しないでください。URLSearchParams が符号化も復号も同じ値の複数指定も扱います。必ず文字列で返ること、空とキー無しの見分け、+ と %20 の違いまで実行して確かめます。

実行して検証済み処理系Node 22.22.3対応ES2015難易度●●○○○目安8更新

答え

split() で自分で分解しないでください。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
猫 2
javascript
const params = new URLSearchParams('page=2');
const page = params.get('page');

console.log(typeof page);
console.log(page + 1);
string 21

先頭の ? は付いていても付いていなくても構いません。 復号は自動です。%E7%8C%AB のままにはなりません。

これは言語ではなくブラウザ側の仕様(URL Standard)ですが、Node にも同じものが入っています。どちらでも同じように使えます。

値は必ず文字列で返る

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
3
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
"" null true false

足し算のつもりが繋がりました。 数として使うなら、その場で変換してください。

javascript
const params = new URLSearchParams('keyword=');

console.log(JSON.stringify(params.get('keyword') || 'すべて'));
console.log(JSON.stringify(params.get('keyword') ?? 'すべて'));
"すべて" ""
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
a [ 'a', 'b' ]

文字列を数値に変換する

無いキーは null

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
q=%E7%8C%AB+%E7%8A%AC&page=2
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
page=2&tag=a&tag=b page=2&tag=c tag=c

「空で指定されている」と「そもそも無い」は別です。 get() だけでは見分けられないので、has() を使ってください。

既定値を入れるときも、この差が効きます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
https://codetaizen.com/ja/search/?q=%E7%8C%AB&page=2 /ja/search/ https://codetaizen.com
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
a=x+y x%20y

|| は空文字も既定値に倒します。どちらが正しいかは仕様しだいです。 → ?. と ??

同じキーが複数あるとき

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
x y x y
javascript
const query = 'q=%E7%8C%AB&tag=a&tag=b';

const parsed = Object.fromEntries(query.split('&').map((part) => part.split('=')));

console.log(parsed);
{ q: '%E7%8C%AB', tag: 'b' }

get()最初の1つしか返しません。 チェックボックスのように複数付きうるものは、必ず getAll() です。

組み立てる

符号化も自動です。 encodeURIComponent() を自分で呼ぶ必要はありません。

したいこと 使うもの
足す(同じキーを増やす) append()
置き換える(同じキーは1つに) set()
消す delete()

set() は同じキーを全部まとめて1つにします。 増やしたいなら append() です。

URL ごと組み立てる

url.searchParams を触ると、url 自身も書き換わります。 文字列を繋いで組み立てるより、こちらのほうが安全です。

スペースが + になる

同じスペースでも書き方が2つあります。 クエリ文字列では + が歴史的に使われ、URLSearchParams はそちらを選びます。

読むときはどちらも正しく戻ります。

自分で encodeURIComponent() した文字列を、さらに set() に渡さないでください。 二重に符号化され、%2520 のような形になります。

よくある間違い:split() で自分で分ける

2つ壊れています。

  • 復号されないので %E7%8C%AB のまま
  • 同じキーが後ろで上書きされて 1つ消えた

値の中に = が入っていれば、そこでも切れます。 自分で書かないでください。

まとめ

  • クエリは URLSearchParams に任せる。split() で分けない
  • 返るのは必ず文字列。数として使うなら変換する
  • 無いキーは null、空指定は空文字。見分けるなら has()
  • 同じキーが複数あるなら getAll()
  • 足すのは append()、置き換えるのは set()
  • 符号化は自動。自分で符号化してから渡さない
  • URL ごと扱うなら new URL()searchParams

この記事の根拠

  1. URLSearchParams — URL Standard (WHATWG)url.spec.whatwg.org
  2. URL — URL Standard (WHATWG)url.spec.whatwg.org
  3. URLSearchParams — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)