Retrofit — 多个具有相同名称的查询参数,其中名称是动态设置的

anr*_*nro 6 java android retrofit2

我正在尝试将一个旧项目迁移到 Retrofit 库,并且该项目有相当棘手的 API。所以我有一个这样的查询模板:

@GET(value = "products/search")
Single<ProductSearchResponse> productSearch();
Run Code Online (Sandbox Code Playgroud)

我必须在以下模板中添加一些参数:

filter[attributeId]=attributeValueId
Run Code Online (Sandbox Code Playgroud)

例如:

products/search?filter[1]=10&filter[1]=11&filter[2]=20&filter[2]=21
Run Code Online (Sandbox Code Playgroud)

这就是 API 的工作方式,我无法更改它。我知道我们可以传递一个列表作为参数,如下所示:

@Query("filter") List<Integer> attributeValueIds
Run Code Online (Sandbox Code Playgroud)

但我怎样才能动态设置参数的名称呢?

Eli*_*les 5

您可以使用数组列表!就像下面的代码一样。

@GET(value = "products/search")
Single<ProductSearchResponse> productSearch(
    @Query("status") List<Integer> status
);


ArrayList<Integer> queryStatus = new ArrayList<>();
queryStatus.add(0);
queryStatus.add(1);
queryStatus.add(2);

productService.productSearch(queryStatus);
Run Code Online (Sandbox Code Playgroud)

你的网址将是这样的 -> {url}?status=0&status=1&status=2


anr*_*nro 2

感谢@ILLIA DEREVIANKO( https://github.com/square/retrofit/issues/1324 )发布的链接,我已经成功解决了此类的问题:

   public class ProxyRetrofitQueryMap extends HashMap<String, Object> {
    public ProxyRetrofitQueryMap(Map<String, Object> m) {
        super(m);
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        Set<Entry<String, Object>> originSet = super.entrySet();
        Set<Entry<String, Object>> newSet = new HashSet<>();

        for (Entry<String, Object> entry : originSet) {
            String entryKey = entry.getKey();
            if (entryKey == null) {
                throw new IllegalArgumentException("Query map contained null key.");
            }
            Object entryValue = entry.getValue();
            if (entryValue == null) {
                throw new IllegalArgumentException(
                        "Query map contained null value for key '" + entryKey + "'.");
            }
            else if(entryValue instanceof List) {
                for(Object arrayValue:(List)entryValue)  {
                    if (arrayValue != null) { // Skip null values
                        Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, arrayValue);
                        newSet.add(newEntry);
                    }
                }
            }
            else {
                Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, entryValue);
                newSet.add(newEntry);
            }
        }
        return newSet;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样我们就可以使用一个映射,其中键是唯一的参数名称,值是字符串列表,它们是该参数的值。像这样的东西:

ProxyRetrofitQueryMap map = new ProxyRetrofitQueryMap();

    List<String> values1 = new ArrayList<>();
    values1.add("10");
    values1.add("11");
    map.put("filter[1]", values1);

    List<String> values2 = new ArrayList<>();
    values1.add("20");
    values1.add("21");
    map.put("filter[2]", values2);
Run Code Online (Sandbox Code Playgroud)