Uri.getQueryParameter()不使用“[”和“]”符号

问题描述 投票:3回答:2

我有以下Uri:http:// host / path?param1 = 1&param2 [] = 2&param3 [1] = 3

uri.getQueryParameterNames()返回一个值为[“param1”,“param2 []”,“param3 [1]”]的数组,这是预期的。

但是当将这些值传递给getQueryParameter时,我得到:uri.getQueryParameter(“param1”)==“1”uri.getQueryParameter(“param2 []”)== null uri.getQueryParameter(“param3 [1]”)== null

我试过没有括号部分传递参数的名称,它也不起作用。也调用getQueryParameters()不起作用。

谢谢你的帮助!

android uri
2个回答
11
投票

documentation所述,Uri构建并解析符合RFC 2396的URI引用。

如果向下滚动到规范中的第2.4.3节,您将找到以下内容:

其他字符被排除在网关和其他传输之外 已知代理有时会修改这些字符,或者它们是 用作分隔符。

unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "“`

必须转义与排除字符对应的数据,以便在URI中正确表示。

从代码的角度来看,Uri有一个私有方法来确定是否允许一个字符 - 如果不允许,它将被编码。理论上,这应该返回false括号和其他特殊字符。

/**
 * Returns true if the given character is allowed.
 *
 * @param c character to check
 * @param allow characters to allow
 * @return true if the character is allowed or false if it should be
 *  encoded
 */
private static boolean isAllowed(char c, String allow) {
    return (c >= 'A' && c <= 'Z')
            || (c >= 'a' && c <= 'z')
            || (c >= '0' && c <= '9')
            || "_-!.~'()*".indexOf(c) != NOT_FOUND
            || (allow != null && allow.indexOf(c) != NOT_FOUND);
}

话虽这么说,现在我们到了有趣的部分。看起来Uri.parse()相当'懒惰',因为它实际上并不编码你给它的uri。在您的场景中,您可能通过调用以下方法构建Uri

Uri uri = Uri.parse("http://host/path?param1=1&param2[]=2&param3[1]=3");

当你开始在生成的getQueryParameter()上调用Uri时,会发生什么是后备数据(String)是'未编码',但是你提供给这些方法的参数名称会被编码。例如:

uri.getQueryParameter("param2[]")

实际上是:

uri.getQueryParameter("param2%5B%5D")

param2%5B%5D中显然不存在具有键Uri的查询参数。

解决方案是确保首先转义括号,或使用Uri.Builder。例如:

Uri uri = Uri.parse("http://host/path").buildUpon()
    .appendQueryParameter("param1", "1")
    .appendQueryParameter("param2[]", "2")
    .appendQueryParameter("param3[1]", "3")
    .build();

这将导致以下基础uri:

http://host/path?param1=1&param2%5B%5D=2&param3%5B1%5D=3

然后你可以毫无问题地调用uri.getQueryParameter("param3[1]"):它将返回3


编辑:我收回我所说的关于Uri.parse()懒惰的说法。它的目的是这样。正如Javadoc中明确提到的那样:

创建一个解析给定编码URI字符串的Uri。

换句话说:您提供的用于解析的字符串应该已经正确编码。


1
投票

我遇到了同样的问题。感谢MH。的回答,我找到了一个快速解决方案。

而不是使用Uri.getQueryParameter(),使用UrlQuerySanitizer.getParameterList()此方法,编码必要的参数并正确获取值。

这是一个简单的例子:

HashMap<String,String> queryMap = new HashMap<>();
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(urlString);
List<UrlQuerySanitizer.ParameterValuePair> sanitizerParameterList = sanitizer.getParameterList();

for (UrlQuerySanitizer.ParameterValuePair valuePair : sanitizerParameterList) {
    queryMap.put(valuePair.mParameter, valuePair.mValue);
}
© www.soinside.com 2019 - 2024. All rights reserved.