使用Retrofit v1.9.0添加重复的参数 [英] Adding duplicate parameters with Retrofit v1.9.0

查看:53
本文介绍了使用Retrofit v1.9.0添加重复的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此处,但我的情况有所不同.

There's a similar question asked here, but my case is a bit different.

我正在尝试发出类似于以下内容的请求:

I'm trying to make a request similar to the following:

http://www.example.com/abc?foo = def& foo = ghi& foo = jkl& bar = xyz

我有两个使事情变得困难的问题.首先,重复的参数(多次为"foo"设置值)阻止了 QueryMap 的使用(我无法选择以不同的方式传递查询字符串中的值,例如数组)).其次,我使用的查询参数是动态的,因此我无法真正使用 Query 并为其提供给定参数名称的值列表,因为我不知道参数名称直到我提出要求为止.

I have two issues that are making things difficult. First, the repeated parameter (setting values for "foo" multiple times) is preventing the use of QueryMap (I don't have the option to pass the values in the query string differently, like as an array). Second, the query parameters I'm using are sort of dynamic, so I can't really use Query and supply it a list of values for a given parameter name since I won't know the parameter names until I am making the request.

我要从中升级的代码使用的是较旧版本的Retrofit,但是不知何故,它具有 QueryList 的概念,该概念采用了 List > NameValuePair 传递查询参数作为名称(及其值作为值),并允许重复的参数.在Retrofit的源代码历史记录中或在Web上的任何地方都找不到对 retrofit.http.QueryList 的引用,因此我不确定这是否是自定义添加项.无论如何,我都试图找到在最新版本中复制该功能的最佳方法,以便能提供任何帮助!

The code I'm trying to upgrade from is using an older version of Retrofit, but somehow it has a concept of a QueryList which took a List of NameValuePairs to pass in query parameters as the name (and their values as the value) and allowing duplicate parameters. I don't see a reference to retrofit.http.QueryList anywhere in Retrofit's source code history or on the web, so I'm not sure if this was a custom addition at the time. In any case, I'm trying to find the best way to replicate that functionality in the latest version so any help would be appreciated!

推荐答案

作为后续,我能够通过使用 QueryMap 和一些技巧来解决此问题.基本上,我将 NameValuePair List 转换为HashMap,在其中检查我是否已经拥有密钥,如果这样做,我会将相同密钥的新值附加到旧值.因此,本质上(键,值)将变成(键,值和键=值2).这样,在构造查询字符串时,将根据需要设置key = value& key = value2.为了使它起作用,我需要自己处理编码值,以便不会对包含在值中的其他与"号和等号进行编码.

To follow-up, I was able to resolve this by using QueryMap and a bit of a hack. Basically I turn my List of NameValuePairs into a HashMap where I check if I already have the key, and if I do I append the new value for the same key to the old value. So essentially (key, value) would turn into (key, value&key=value2). This way when the query string is constructed, I'll have key=value&key=value2 as desired. In order for that to work, I need to handle the value encoding myself so that the additional ampersands and equal signs that I'm including in the value don't get encoded.

因此 HashMap 是通过 List 构造的,如下所示:

So the HashMap is constructed from the List like this:

public static HashMap<String, String> getPathMap(List<NameValuePair> params) {
    HashMap<String, String> paramMap = new HashMap<>();
    String paramValue;

    for (NameValuePair paramPair : params) {
        if (!TextUtils.isEmpty(paramPair.getName())) {
            try {
                if (paramMap.containsKey(paramPair.getName())) {
                    // Add the duplicate key and new value onto the previous value
                    // so (key, value) will now look like (key, value&key=value2)
                    // which is a hack to work with Retrofit's QueryMap
                    paramValue = paramMap.get(paramPair.getName());
                    paramValue += "&" + paramPair.getName() + "=" + URLEncoder.encode(String.valueOf(paramPair.getValue()), "UTF-8");
                } else {
                    // This is the first value, so directly map it
                    paramValue = URLEncoder.encode(String.valueOf(paramPair.getValue()), "UTF-8");
                }
                paramMap.put(paramPair.getName(), paramValue);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    return paramMap;
}

然后我的请求如下:

@GET("/api/")
List<Repo> listRepos(@QueryMap(encodeValues=false) Map<String, String> params);

我的服务电话如下:

// Get the list of params for the service call
ArrayList<NameValuePair> paramList = getParams();

// Convert the list into a map and make the call with it
Map<String, String> params = getPathMap(paramList);
List<Repo> repos = service.listRepos(params);

最初,我尝试使用 Path 解决方案,其中尝试手动构造查询字符串,但是查询字符串中不允许使用替换块,因此我选择了QueryMap解决方案.希望这对遇到相同问题的其他人有所帮助!

I originally tried a solution using Path where I tried to manually construct the query string, but replacement blocks are not allowed in the query string so I went with this QueryMap solution. Hopefully this helps anyone else that runs into the same issue!

这篇关于使用Retrofit v1.9.0添加重复的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆