如何从查询字符串中删除查询参数

时间:2016-12-09 15:38:57

标签: java

我正在使用UriBuilder从URI中删除参数:

public static URI removeParameterFromURI(URI uri, String param) {
    UriBuilder uriBuilder = UriBuilder.fromUri(uri);
    return uriBuilder.replaceQueryParam(param, "").build();
}

public static String removeParameterFromURIString(String uriString, String param) {
    try {
        URI uri = removeParameterFromURI(new URI(uriString), param);
        return uri.toString();
    } catch (URISyntaxException e) {
        throw new RuntimeException(e);
    }
}

上述作品并修改:

http://a.b.c/d/e/f?foo=1&bar=2&zar=3

...进入:

http://a.b.c/d/e/f?bar=&foo=1&zar=3

但它有以下问题:

  1. 它弄乱了参数的顺序。我知道订单不相关,但它仍然困扰着我。
  2. 它没有完全删除参数,只是将其值设置为空字符串。我更喜欢的是参数是从查询字符串中完全删除的。
  3. 是否有一些标准或常用的库可以实现上述整洁而无需自己解析和破解查询字符串?

11 个答案:

答案 0 :(得分:3)

如果可以的话,使用httpclient URIBuilder会更加清晰。

public String removeQueryParameter(String url, String parameterName) throws URISyntaxException {
    URIBuilder uriBuilder = new URIBuilder(url);
    List<NameValuePair> queryParameters = uriBuilder.getQueryParams();
    for (Iterator<NameValuePair> queryParameterItr = queryParameters.iterator(); queryParameterItr.hasNext();) {
        NameValuePair queryParameter = queryParameterItr.next();
        if (queryParameter.getName().equals(parameterName)) {
            queryParameterItr.remove();
        }
    }
    uriBuilder.setParameters(queryParameters);
    return uriBuilder.build().toString();
}

答案 1 :(得分:2)

使用流和URIBuilder from httpclient它看起来像这样

public String removeQueryParameter(String url, String parameterName) throws URISyntaxException {
    URIBuilder uriBuilder = new URIBuilder(url);
    List<NameValuePair> queryParameters = uriBuilder.getQueryParams()
              .stream()
              .filter(p -> !p.getName().equals(parameterName))
              .collect(Collectors.toList());
    if (queryParameters.isEmpty()) {
        uriBuilder.removeQuery();
    } else {
        uriBuilder.setParameters(queryParameters);
    }
    return uriBuilder.build().toString();
}

答案 2 :(得分:1)

要完全删除参数,您可以使用

public static URI removeParameterFromURI(URI uri, String param) {
    UriBuilder uriBuilder = UriBuilder.fromUri(uri);
    return uriBuilder.replaceQueryParam(param, (Object[]) null).build();
}

答案 3 :(得分:0)

我不确定是否有一些库需要帮助,但我只是将字符串拆分为“?”并采取下半部分并将其拆分为“&amp;”。然后我会相应地重建字符串。

    public static void main(String[] args) {
        // TODO code application logic here
        System.out.println("original: http://a.b.c/d/e/f?foo=1&bar=2&zar=3");
        System.out.println("new     : " + fixString("http://a.b.c/d/e/f?foo=1&bar=2&zar=3"));
    }

    static String fixString(String original)
    {
        String[] processing = original.split("\\?");
        String[] processing2ndHalf = processing[1].split("&");

        return processing[0] + "?" + processing2ndHalf[1] + "&" + processing2ndHalf[0] + "&" + processing2ndHalf[2];
    }
  

输出:

enter image description here

要删除参数,只需将其从返回字符串中删除即可。

答案 4 :(得分:0)

基于JB Nizzet的建议,这就是我最终要做的事情(我添加了一些额外的逻辑,以便能够断言我是否希望参数存在,如果存在,那么多少次):

public static URI removeParameterFromURI(URI uri, String parameter, boolean assertAtLeastOneIsFound, Integer assertHowManyAreExpected) {
    Assert.assertFalse("it makes no sense to expect 0 or less", (assertHowManyAreExpected!=null) && (assertHowManyAreExpected<=0) );
    Assert.assertFalse("it makes no sense to not assert that at least one is found and at the same time assert a definite expected number", (!assertAtLeastOneIsFound) && (assertHowManyAreExpected!=null) );
    String queryString = uri.getQuery();
    if (queryString==null)
        return uri;
    Map<String, List<String>> params = parseQuery(queryString);
    Map<String, List<String>> paramsModified = new LinkedHashMap<>();
    boolean found = false;
    for (String key: params.keySet()) {
        if (!key.equals(parameter))
            Assert.assertNull(paramsModified.put(key, params.get(key)));
        else {
            found = true;
            if (assertHowManyAreExpected!=null) {
                Assert.assertEquals((long) assertHowManyAreExpected, params.get(key).size());
            }
        }
    }
    if (assertAtLeastOneIsFound)
        Assert.assertTrue(found);
    UriBuilder uriBuilder = UriBuilder.fromUri(uri)
        .replaceQuery("");
    for (String key: paramsModified.keySet()) {
        List<String> values = paramsModified.get(key);
        uriBuilder = uriBuilder.queryParam(key, (Object[]) values.toArray(new String[values.size()]));
    }
    return uriBuilder.build();
}

public static String removeParameterFromURI(String uri, String parameter, boolean assertAtLeastOneIsFound, Integer assertHowManyAreExpected) {
    try {
        return removeParameterFromURI(new URI(uri), parameter, assertAtLeastOneIsFound, assertHowManyAreExpected).toString();
    } catch (URISyntaxException e) {
        throw new RuntimeException(e);
    }
}

private static Map<String, List<String>> parseQuery(String queryString) {
    try {
        final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
        final String[] pairs = queryString.split("&");
        for (String pair : pairs) {
            final int idx = pair.indexOf("=");
            final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8.name()) : pair;
            if (!query_pairs.containsKey(key)) {
                query_pairs.put(key, new ArrayList<String>());
            }
            final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8.name()) : null;
            query_pairs.get(key).add(value);
        }
        return query_pairs;
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
    }
}

答案 5 :(得分:0)

您可以使用基于@Flips解决方案的Collection中的更简单方法:

public String removeQueryParameter(String url, String parameterName) throws URISyntaxException {
    URIBuilder uriBuilder = new URIBuilder(url);
    List<NameValuePair> queryParameters = uriBuilder.getQueryParams();

    queryParameters.removeIf(param -> 
         param.getName().equals(parameterName));

    uriBuilder.setParameters(queryParameters);

    return uriBuilder.build().toString();
}

答案 6 :(得分:0)

在Android中,不导入任何库。 我写了一个受此答案启发的util方法Replace query parameters in Uri.Builder in Android?Replace query parameters in Uri.Builder in Android?

希望可以为您提供帮助。下面的代码:

public static Uri removeUriParameter(Uri uri, String key) {
    final Set<String> params = uri.getQueryParameterNames();
    final Uri.Builder newUri = uri.buildUpon().clearQuery();
    for (String param : params) {
        if (!param.equals(key)) {
            newUri.appendQueryParameter(param, uri.getQueryParameter(param));
        }
    }
    return newUri.build();
}

答案 7 :(得分:0)

如果您使用的是Android,并且想使用Uri.Builder,则可以使用

Uri uriWithoutQuery = Uri.parse(urlWithQuery).buildUpon().clearQuery().build();

答案 8 :(得分:0)

public static String removeQueryParameter(String url, List<String> removeNames) {
    try {
        Map<String, String> queryMap = new HashMap<>();
        Uri uri = Uri.parse(url);
        Set<String> queryParameterNames = uri.getQueryParameterNames();
        for (String queryParameterName : queryParameterNames) {
            if (TextUtils.isEmpty(queryParameterName)
                    ||TextUtils.isEmpty(uri.getQueryParameter(queryParameterName))
                    || removeNames.contains(queryParameterName)) {
                continue;
            }
            queryMap.put(queryParameterName, uri.getQueryParameter(queryParameterName));
        }
        // remove all params
        Uri.Builder uriBuilder = uri.buildUpon().clearQuery();

        for (String name : queryMap.keySet()) {
            uriBuilder.appendQueryParameter(name, queryMap.get(name));
        }
        return uriBuilder.build().toString();
    } catch (Exception e) {
        return url;
    }
}

答案 9 :(得分:0)

@TTKatrina's answer对我有用,但是我也需要从片段中删除查询参数。因此,将其扩展为片段,并提出了这个建议。

fun Uri.removeQueryParam(key: String): Uri {

    //Create new Uri builder with no query params.
    val builder = buildUpon().clearQuery()

    //Add all query params excluding the key we don't want back to the new Uri.
    queryParameterNames.filter { it != key }
        .onEach { builder.appendQueryParameter(it, getQueryParameter(it)) }

    //If query param is in fragment, remove from it.
    val fragmentUri = fragment?.toUri()
    if (fragmentUri != null) {
        builder.encodedFragment(fragmentUri.removeQueryParam(key).toString())
    }

    //Now this Uri doesn't have the query param for [key]
    return builder.build()
}

答案 10 :(得分:0)

以下代码对我有用:

代码:

import java.util.Arrays;
import java.util.stream.Collectors;

public class RemoveURL {

    public static void main(String[] args) {
        final String remove = "password";
        final String url = "http://testdomainxyz.com?username=john&password=cena&password1=cena";
        System.out.println(url);
        System.out.println(RemoveURL.removeParameterFromURL(url, remove));
    }

    public static String removeParameterFromURL(final String url, final String remove) {
        final String[] urlArr = url.split("\\?");
        final String params = Arrays.asList(urlArr[1].split("&")).stream()
                .filter(item -> !item.split("=")[0].equalsIgnoreCase(remove)).collect(Collectors.joining("&"));
        return String.join("?", urlArr[0], params);
    }
}

输出

http://testdomainxyz.com?username=john&password=cena&password1=cena
http://testdomainxyz.com?username=john&password1=cena