tl; dr
-
2020年7月時点、dart:coreのUriクラスを使うとクエリパラメータで配列末尾以外の値が失われることがある
-
http_interceptor ライブラリで発生することを確認
- APIまわりのコードをOpenAPI Generator (for Dart)で生成していたので、WorkaroundとしてQueryParameterのスタイルに
explode: false
指定を追加
※ QueryParameterの配列スタイルをhttps://example.com/foo?ids=1&ids=2&ids=3
からhttps://example.com/foo?ids=1,2,3
に変更
確認環境
- dart : 2.8.4
- http_interceptor : 0.3.2
- openapi-generator : 4.3.1
原因
dart:coreのUriクラスをStringから生成すると、配列として持っていたQueryParameterが末尾のみに変換されてしまう
final url = Uri.parse('https://example.com/foo?ids=1&ids=2&ids=3');
// https://example.com/foo?ids=1&ids=2&ids=3
print(url);
// {ids: 3}
print(url.queryParameters);
解決方法
OpenAPI Generatorでコード生成している場合
方針
dart:coreのUriクラス依存の問題のため修正を諦め、QueryParameterの形式を修正する。(クライアント/サーバそれぞれ問題なければ)
Before | After |
---|---|
https://example.com/foo?ids=1&ids=2&ids=3 |
https://example.com/foo?ids=1,2,3 |
OpenAPI/Swaggerの形式でQueryParameterの形式を修正するために、parameters:
以下に explode: false
を追加する。
Before
paths:
"/foo":
get:
parameters:
- name: ids
in: query
required: true
schema:
type: array
items:
type: integer
After
paths:
"/foo":
get:
parameters:
- name: ids
in: query
required: true
explode: false
schema:
type: array
items:
type: integer
OpenAPI/Swaggerを上記のように修正してコード生成するとQueryParameterで配列を ?ids=1,2,3
形式で扱うようになり、Uriクラスで値が失われることを避けることができます。
動作確認リポジトリ:https://github.com/gyamoto/dart-http-query-param-trial
補足
他にも style
と explode
の組み合わせで下記パターンの形式に変えることができます。
style | explode | Array id = [3, 4, 5] |
---|---|---|
form * | true * | /users?id=3&id=4&id=5 |
form | false | /users?id=3,4,5 |
spaceDelimited | true | /users?id=3&id=4&id=5 |
spaceDelimited | false | /users?id=3%204%205 |
pipeDelimited | true | /users?id=3&id=4&id=5 |
pipeDelimited | false | /users?id=3 |
deepObject | true | n/a |
参考
- Describing Query Parameters https://swagger.io/docs/specification/describing-parameters/#query-parameters
- Query Parameter Serialization https://swagger.io/docs/specification/serialization/#query
その他の場合
TODO: 解決法が見つかれば、いつか書くかも