👋
【1日1zenn - day15】クエリパラメータの付与から取り出しまで
直近、1日1zennサイズに収まるような何かがあまりなかったので、
一旦小ネタをまとめようかと思います。
とか思ったけど書いてみたら一定のサイズになったからヨシ!
クエリパラメータの作成から取り出しまで
自分はFEをReactとTypeScript、BEをKotlinとSpring Bootで開発してるので、それメインになります。
前提メモ
ちゃんと構造化されたデータを受け取ったりしたいときはJSON形式にするのが普通だけど、自分の案件では個人情報などとは一切関係ない(セキュリティリスクがない)単一のデータをPOSTする時とかにもパラメータで書いたりしてる。
[FE]クエリパラメータの作成
URL全体を作る場合
このパッケージが主要そう。
インストール
npm install url-join
作成するコード例
import urlJoin from 'url-join';
const fullUrl = urlJoin('http://www.google.com', 'a', '/b/cd', '?foo=123');
上記で作成されたURL
http://www.google.com/a/b/cd?foo=123
ソースコードを見ると、
?
とかのパラメータ記号がついていたり、すでに/
がついている場合は/
をつけない処理がありそうですね。
これでURIパスやクエリパラメータを作れそう。
単純にパラメータだけを作る場合
URLSearchParamsを使い、以下みたいにやれそう
const params = new URLSearchParams();
params.append("key", "value");
params.append("page", "1");
params.append("size", "10");
const url = `https://example.com/search?${params.toString()}`;
console.log(url); // https://example.com/search?key=value&page=1&size=10
[BE]クエリパラメータの作成
UriComponentsBuilderを使うのが一般的そう。
UriComponentsBuilderは色々メソッドあるけど、以下を使いそう
- fromUriString(パラメをつけたいURIの文字列)
- 元のURIの中で、どこがクエリパラメータでどこがドメインかなどがわかるらしい
- 既存のクエリを保持したりするために使う
- '='や'&'みたいな予約語がある場合に正常に動くよう担保したり
- queryParams(つけたいパラメータ)
- つけたいパラメータはNullableで
MultiValueMap<String,String>
を受け取る - 値が指定されていない場合はクエリパラメータ名のみが追加される(例: "?foo=bar" ではなく "?foo")とドキュメントに書いてあるけど、なんか動作確認したらnullで受け取った場合にクエリパラメータ名も入らない場合もあったのでよくわからぬ
- つけたいパラメータはNullableで
- toUriString()
- URI文字列を作る
以下みたいな感じ
UriComponentsBuilder.fromUriString(パラメをつけたいURIの文字列).queryParams(つけたいパラメータ群).toUriString()
そしてつけたいパラメータはMultiValueMapである必要があるので、以下みたいにパラメータを作る
private fun buildParams(userId: String, isPermit: Boolean): String {
val params = LinkedMultiValueMap<String, String>()
params.add("userId", userId)
params.add("isPermit", isPermit.toString)
return params
}
これでUriを作るメソッドを以下みたいに準備してる場合は、
private fun buildUriWithParams(baseUri: String, params: MultiValueMap<String, String>): String {
return UriComponentsBuilder.fromUriString(baseUri)
.queryParams(params)
.toUriString()
}
として、buildParamsで以下みたいに呼び出す
private fun buildParams(baseUri: String, userId: String, isPermit: Boolean): String {
val params = LinkedMultiValueMap<String, String>()
params.add("userId", userId)
params.add("isPermit", isPermit.toString)
return buildUriWithParams(baseUri, params)
}
など。
[FE]クエリパラメータの受取
URLSearchParamsを使い、以下みたいにやれそう
const decodeSearch = decodeURIComponent(location.search)
const urlSearchParams = new URLSearchParams(decodeSearch)
const userId = urlSearchParams.get("userId")
- まずURLの検索文字列をlocation.searchで取得し、エンコードされている場合はdecodeURIComponentに渡してデコードする
- URLSearchParamsにデコードしたURLを渡してインスタンスを作る
- getメソッドにキーの文字列を渡す
[BE]クエリパラメータの受取
以下みたいな感じ
@PostMapping("/confirm-message")
fun confirmMessage(
@RequestParam(required = false) name: String,
@RequestParam(required = false) message: String,
model: Model
): String{
model.addAttribute("name", name)
model.addAttribute("message", message)
return "confirm_message"
}
- 上記みたいにするとnameとかmessageとかを受け取れる。
-
@RequestParam
というアノテーションでパラメータを作る- required = falseで任意項目にでき、defaultValueで入力されなかった場合の値を決められる
おわり
なんか掘れば色々ありそうで、渡し方に困ったらまた調べよう。
明日は、ちょっとフロントで作りたい挙動があるけど体力次第かなぁ。
積み残しの整理もしたい。
Discussion