6

I am using UriBuilder to remove a parameter from a 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);
    }
}

The above sort of works and modifies:

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

… into:

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

But it has the following issues:

  1. It messes up the order of the parameters. I know that the order is not relevant but it still bothers me.
  2. it doesn't fully remove the parameter, it just sets its value to the empty string. I would prefer is the parameter is completely removed from the query string.

Is there some standard or commonly used library that can achieve the above neatly without having to parse and hack the query string myself?

3
  • UriBuilder does not have a method to remove a query parameter, you can only add or replace. Commented Dec 9, 2016 at 15:43
  • I am not sure if there is some library to help, but I would just split the string on "?" and take the second half and split it on "&". Then I would rebuild the string accordingly. Is your seconds string suppposed to be bar=2? Commented Dec 9, 2016 at 15:43
  • 2
    Or you could reconstruct a second URL from scratch using the builder, adding all the parts of the original URL, except the param you want to remove. Commented Dec 9, 2016 at 15:48

11 Answers 11

10

In Android, without import any library. I write a util method inspired by this answerReplace query parameters in Uri.Builder in Android?(Replace query parameters in Uri.Builder in Android?)

Hope can help you. Code below:

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();
}
Sign up to request clarification or add additional context in comments.

Comments

5

If you are on Android and want to remove all query parameters, you can use

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

4 Comments

This would remove all get parameters, and is not what the question was asking.
@gardenofwine Thanks for pointing it out, I had misread the question. I've adapted the answer.
Your answer now has internal sense, but it still answers the wrong question, and can be misleading to visitors of this page.
This is a great answer that I wanted to clear all query params
4

Using httpclient URIBuilder would be much cleaner if you can.

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

Comments

3

To fully remove the parameter, you can use

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

1 Comment

I think this is using org.springframework.web.util.UriComponentsBuilder, but if so the static factory method is now on the UriComponentsBuilder implementation.
2

Using streams and URIBuilder from httpclient it would look like this

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

Comments

2

The following piece of code worked for me:

Code:

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

Output

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

1 Comment

God Java sucks. In every other language you can just call a remove('param') method
1

Based on the suggestion by JB Nizzet, this is what I ended up doing (I added some extra logic to be able to assert whether I expect the parameter to be present, and if so, how many times):

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

Comments

1

You can use simpler method from Collection based on @Flips solution:

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

Comments

0

I am not sure if there is some library to help, but I would just split the string on "?" and take the second half and split it on "&". Then I would rebuild the string accordingly.

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

Output:

enter image description here

To remove a paramater just remove it from the return string.

Comments

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

Comments

-1

@TTKatrina's answer worked for me, but I need to remove query param from fragment too. So extended that for fragment and came up with this.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.