【问题标题】:how to remove a query parameter from a query string如何从查询字符串中删除查询参数
【发布时间】:2016-12-09 15:38:57
【问题描述】:

我正在使用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. 它不会完全删除参数,它只是将其值设置为空字符串。我希望参数完全从查询字符串中删除。

是否有一些标准或常用的库可以巧妙地实现上述目标,而无需自己解析和破解查询字符串?

【问题讨论】:

  • UriBuilder 没有删除查询参数的方法,只能添加或替换。
  • 我不确定是否有一些库可以提供帮助,但我只想将字符串拆分为“?”并取下半部分并将其拆分为“&”。然后我会相应地重建字符串。你的秒字符串应该是 bar=2 吗?
  • 或者您可以使用构建器从头开始重建第二个 URL,添加原始 URL 的所有部分,但要删除的参数除外。

标签: java


【解决方案1】:

在 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();
}

【讨论】:

    【解决方案2】:

    如果可以的话,使用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();
    }
    

    【讨论】:

      【解决方案3】:

      如果您在 Android 上并想删除 所有 查询参数,您可以使用

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

      【讨论】:

      • 这将删除所有获取参数,这不是问题所在。
      • @gardenofwine 感谢您指出,我误读了这个问题。我已经修改了答案。
      • 您的答案现在具有内在意义,但它仍然回答了错误的问题,并且可能会误导该页面的访问者。
      【解决方案4】:

      使用流和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();
      }
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          根据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);
              }
          }
          

          【讨论】:

            【解决方案7】:

            您可以使用基于 @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();
            }
            

            【讨论】:

              【解决方案8】:

              以下代码对我有用:

              代码:

              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
              

              【讨论】:

                【解决方案9】:

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

                    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];
                    }
                

                输出:

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

                【讨论】:

                  【解决方案10】:
                  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;
                      }
                  }
                  

                  【讨论】:

                    【解决方案11】:

                    @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()
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-09-06
                      • 2021-05-05
                      • 2012-06-21
                      • 2010-12-10
                      • 1970-01-01
                      相关资源
                      最近更新 更多