Filter parameters from query string (using Guava?)

Take this HTTP String request:

foo=fooValue&bar=barValue&phleem=phleemValue

Or this one:

bar=barValue&phleem=phleemValue&foo=someOtherFoo

What would be the best way to remove a parameter foo?

All Java solutions are welcome, but Guava prefers.

(ServletContext is not available, therefore Servlet methods will not help)

Update: The method must process several parameters for deletion.

+3
source share
4 answers

This is not the most elegant solution, but it works the way you expect:

private String removeParameter(String string, final String parameterName) {
    List<String> list = newArrayList(string.split("&"));

    Collection<String> filtered = Collections2.filter(list, new Predicate<String>() {
        public boolean apply(String s) {
            return !s.startsWith(parameterName + "=");
        }
    });

    return Joiner.on("&").join(filtered);
}

UPDATE

To process several parameters:

@Test
public void removesMultipleParametersFromQuery() throws Exception {
    String result = removeParameters("foo=fooValue&zee=lalal&bar=barValue&phleem=phleemValue", "foo", "bar");
    assertThat(result, is("zee=lalal&phleem=phleemValue"));
}

private String removeParameters(String query, final String...parameterNames) {
    List<String> list = newArrayList(query.split("&"));
    return Joiner.on("&").join(filter(list, startsWithAnyOf(parameterNames)));
}

private Predicate<String> startsWithAnyOf(final String[] parameterNames) {
    return new Predicate<String>() {
        public boolean apply(String s) {
            return !Iterables.any(newArrayList(parameterNames), isPrefixOf(s));
        }
    };
}

private Predicate<String> isPrefixOf(final String string){
    return new Predicate<String>() {
        public boolean apply(String candidate) {
            return string.startsWith(candidate);
        }
    };
}
+3
source

Here is my own solution (but it is ugly as hell):

public static String removeParameters(final String queryString,
    final String... paramNames){
    Iterable<Predicate<CharSequence>> innerPredicates;
    if(paramNames.length == 0){
        innerPredicates = Collections.emptySet();
    } else{
        innerPredicates =
            Iterables.transform(
            Arrays.asList(paramNames),
                new Function<String, Predicate<CharSequence>>(){

                    @Override
                    public Predicate<CharSequence> apply(
                        final String input){

                        return Predicates.contains(
                            Pattern.compile("^"
                            + Pattern.quote(input) + "=")
                        );
                    }
                });
    }

    final Predicate<CharSequence> predicate =
        Predicates.not(Predicates.or(innerPredicates));
    return Joiner.on("&").join(
        Iterables.filter(Splitter.on('&').split(queryString), predicate));
}
+1
source

- Multimap<String, String> - Multimap<String, String> . , removeAll(parameter) , . - raw String, , .

Here is the code for this:

private static final Splitter QUERY_SPLITTER = Splitter.on(CharMatcher.anyOf("&;"));
private static final Joiner QUERY_JOINER = Joiner.on('&');
private static final EntrySplitFunction ENTRY_SPLITTER = 
    new EntrySplitFunction(Splitter.on('='));
private static final EntryJoinFunction ENTRY_JOINER = 
    new EntryJoinFunction(Joiner.on('=').useForNull(""));

public static Multimap<String, String> parseQueryString(String queryString) {
  Multimap<String, String> result = HashMultimap.create();
  Iterable<String> entryStrings = QUERY_SPLITTER.split(queryString);
  for (Map.Entry<String, String> entry : transform(entryStrings, ENTRY_SPLITTER)) {
    result.put(entry.getKey(), entry.getValue());
  }
  return result;
}

public static String toQueryString(Multimap<String, String> multimap) {
  return QUERY_JOINER.join(transform(multimap.entries(), ENTRY_JOINER));
}

private static class EntrySplitFunction 
    implements Function<String, Map.Entry<String, String>> {
  private final Splitter keyValueSplitter;

  private EntrySplitFunction(Splitter keyValueSplitter) {
    this.keyValueSplitter = keyValueSplitter;
  }

  @Override public Map.Entry<String, String> apply(String input) {
    Iterator<String> keyAndValue = keyValueSplitter.split(input).iterator();
    return Maps.immutableEntry(keyAndValue.next(), keyAndValue.next());
  }
}

private static class EntryJoinFunction 
    implements Function<Map.Entry<String, String>, String> {
  private final Joiner keyValueJoiner;

  private EntryJoinFunction(Joiner keyValueJoiner) {
    this.keyValueJoiner = keyValueJoiner;
  }

  @Override public String apply(Map.Entry<String, String> input) {
    return keyValueJoiner.join(input.getKey(), input.getValue());
  }
}

Moreover, all you need to do to implement your method is:

public static String removeParameters(String queryString, String... parameters) {
  Multimap<String, String> query = parseQueryString(queryString);
  for (String parameter : parameters) {
    query.removeAll(parameter);
  }
  return toQueryString(query);
}

Even better, assuming that you are doing something else with the request, you will only Multimaphave it when you achieve what you need to do, and you don’t even bother to write a special method for it.

+1
source

You can use guava

public static String toQueryString(final Map<String, Object> queryParameters) {
        return "?" + Joiner.on('&').withKeyValueSeparator("=").join(queryParameters);
    }
0
source

Source: https://habr.com/ru/post/1783435/


All Articles