【问题标题】:Add an array as request parameter with Retrofit 2使用 Retrofit 2 添加一个数组作为请求参数
【发布时间】:2020-07-23 18:13:08
【问题描述】:

我正在寻找在带有改造 2 的 GET 请求中添加一个 int 数组(例如 [0,1,3,5])作为参数的方法。然后,生成的 url 应该是像这样:http://server/service?array=[0,1,3,5]

如何做到这一点?

【问题讨论】:

  • 对邮递员有用吗?

标签: android retrofit retrofit2


【解决方案1】:

只需将其添加为查询参数

@GET("http://server/service")
Observable<Void> getSomething(@Query("array") List<Integer> array);

您也可以使用 int[] 或 Integer... 作为最后一个参数;

【讨论】:

  • 我已经尝试过这个解决方案,但生成的 url 看起来像这样:server/service?array=0&array=1&array=3&array=5 但我的情况是我正在寻找一种方法来获取看起来像这样的生成 url server/service?array=[0,1,3,5]
  • 现在这不是很标准的方法。您可以尝试 server.service?array=[{array}] 并在请求中使用 @Path("array") String 并用您的数组生成的字符串提供它。但我不确定这是否可以通过改造。或者,您可以尝试将其作为查询参数推送。 @Query("array) 并在您的情况下手动生成您需要的字符串 "[1,2,3]"
  • @AndrejJurkin 使用@path 的方式无法通过Retrofit:java.lang.IllegalArgumentException: URL query string "array={array}" must not have replace block. For dynamic query parameters use @Query.
【解决方案2】:

您需要使用如下数组语法命名您的查询参数:

@GET("http://server/service")
Observable<Void> getSomething(@Query("array[]") List<Integer> array);

语法本身会因所使用的后端技术而异,但不包括括号“[]”通常会被解释为单个值。

例如,使用array=1&amp;array=2 通常会被后端解释为仅array=1array=2 而不是array=[1,2]

【讨论】:

  • 对我不起作用。 https:/server/service?array[]=value1&amp;array[]=value2 是我得到的
  • 这正是你应该得到的@Przemo
  • @mrstif 我认为问题是关于获取array=[1,2],而不是array[]=value1&amp;array[]=value2
  • @XiWei as my answer指出,事实上大多数服务器通常如何解释这些值
【解决方案3】:

我终于找到了一个解决方案,方法是使用 Arrays.toString(int []) 方法并删除此结果中的空格,因为 Arrays.toString 返回“[0, 1, 3, 5]”。而我的请求方法是这样的

@GET("http://server/service")
Observable<Void> getSomething(@Query("array") String array);

【讨论】:

  • 当你 int[] 元素之间有空格时,这不起作用。你的服务器也应该支持字符串中的参数。
【解决方案4】:

我遇到了类似的问题,必须做几件事才能达到可接受的形式(如问题中所要求的那样)。

  1. 将 ArrayList 转换为字符串

    arrayList.toString().replace(" ", "")
    
  2. 在 RetroFit 方法中,我将接受上述 ArrayList 的 Query 参数更改为如下:

    @Query(value = "cities", encoded = true)
    

这样可以确保括号和逗号不是 URL 编码的。

【讨论】:

    【解决方案5】:

    使用toString 对我不起作用。 相反,TextUtils.join(",", ids) 可以解决问题。

    别忘了用encoded = true 标记Query

    【讨论】:

      【解决方案6】:

      这对我有用

      第 1 步:

      StateServce.kt

      @GET("states/v1")
      fun getStatesByCoordinates(@Query("coordinates", encoded = true) coordinates: String) : Call<ApiResponse<List<State>>>
      

      第 2 步

      从存储库调用时

      val mCoordinate : List<Double> = [22.333, 22.22]
      mStateService?.getStatesByCoordinates(mCoordinate.toString().replace(" ", ""))!!
      

      【讨论】:

        【解决方案7】:

        使用Iterable封装整数列表,或者使用二维整数数组。

        • 如何定义:

          public interface ServerService {
              @GET("service")
              Call<Result> method1(@Query("array") Iterable<List<Integer>> array);
          
              @GET("service")
              Call<Result> method2(@Query("array") Integer[][] array);
          }
          
        • 使用方法:

          Retrofit retrofit = new Retrofit.Builder()
              .baseUrl("http://server/")
              .addConverterFactory(GsonConverterFactory.create())
              .build();
          ServerService service = retrofit.create(ServerService.class);
          
          // Use the first method.
          List<Integer> data1 = Arrays.asList(0,1,3,5);
          Iterable array1 = Arrays.asList(data1);
          Call<Result> method1Call = service.method1(array1);
          
          // Use the second method.
          Integer[] data2 = new Integer[]{0,1,3,5};
          Integer[][] array2 = new Integer[][]{data2};
          Call<Result> method2Call = service.method2(array2);
          
          // Execute enqueue() or execute() of method1Call or method2Call.
          

        该方式能解决问题的原因请参考Retrofit2的代码ParameterHandler.java

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-29
          • 1970-01-01
          • 2017-06-27
          • 2015-12-12
          • 2014-03-20
          • 1970-01-01
          • 1970-01-01
          • 2020-01-01
          相关资源
          最近更新 更多