Help us understand the problem. What is going on with this article?

Dartのhttp_interceptorライブラリを使うと配列のクエリパラメータが消えてしまう件の応急処置

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

補足

他にも styleexplode の組み合わせで下記パターンの形式に変えることができます。

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

参考

その他の場合

TODO: 解決法が見つかれば、いつか書くかも

gyamoto
最近はスマホアプリでKotlin, Flutterしている それまではRaspberryPi, Ruby, Kinect, Arduino, JS, Elixirを触ったり
team-lab
最新のテクノロジーを活用したシステムやデジタルコンテンツの開発を行うウルトラテクノロジスト集団
https://www.team-lab.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away