Как преобразовать карту в строку запроса URL? - PullRequest
60 голосов
/ 11 мая 2010

Известны ли вам какие-либо служебные классы / библиотеки, которые могут преобразовать Map в строку запроса, удобную для URL?

Пример:

У меня есть карта:

"param1"=12,
"param2"="cat"

Я хочу получить:

param1=12&param2=cat

конечный результат

relativeUrl+param1=12&param2=cat

Ответы [ 14 ]

1 голос
/ 19 июня 2019

Нет ничего встроенного в Java, чтобы сделать это. Но, эй, Java - это язык программирования, так что давайте запрограммируем его!

map.values().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"))

Это дает вам "param1 = 12 & param2 = cat". Теперь нам нужно объединить URL и этот бит вместе. Вы могли бы подумать, что можете просто сделать: URL + "?" + theAbove, но если URL-адрес уже содержит вопросительный знак, вы должны вместо этого объединить все это вместе с "&". Один из способов проверить это - посмотреть, есть ли где-нибудь вопросительный знак в URL.

Кроме того, я не совсем знаю, что на вашей карте. Если это сырье, вы, вероятно, должны защитить вызов на e.getKey() и e.getValue() с URLEncoder.encode или подобным.

Еще один способ - расширить свой кругозор. Вы пытаетесь добавить содержимое карты к URL-адресу или ... вы пытаетесь сделать HTTP (S) -запрос от java-процесса с содержимым на карте как (дополнительными) HTTP-параметрами? В последнем случае вы можете заглянуть в http-библиотеку, например OkHttp , в которой есть несколько хороших API-интерфейсов для выполнения этой работы, и тогда вы можете отказаться от необходимости возиться с этим URL-адресом.

1 голос
/ 06 марта 2016

Чтобы немного улучшить ответ @ eclipse: В Javaland карта параметров запроса обычно представляется как Map<String, String[]>, Map<String, List<String>> или, возможно, какой-то MultiValueMap<String, String>, что является чем-то вроде того же. В любом случае: параметр обычно может иметь несколько значений. Поэтому решение Java 8 будет выглядеть примерно так:

public String getQueryString(HttpServletRequest request, String encoding) {
    Map<String, String[]> parameters = request.getParameterMap();

    return parameters.entrySet().stream()
            .flatMap(entry -> encodeMultiParameter(entry.getKey(), entry.getValue(), encoding))
            .reduce((param1, param2) -> param1 + "&" + param2)
            .orElse("");
}

private Stream<String> encodeMultiParameter(String key, String[] values, String encoding) {
    return Stream.of(values).map(value -> encodeSingleParameter(key, value, encoding));
}

private String encodeSingleParameter(String key, String value, String encoding) {
    return urlEncode(key, encoding) + "=" + urlEncode(value, encoding);
}

private String urlEncode(String value, String encoding) {
    try {
        return URLEncoder.encode(value, encoding);
    } catch (UnsupportedEncodingException e) {
        throw new IllegalArgumentException("Cannot url encode " + value, e);
    }
}
0 голосов
/ 19 июня 2019

Использование EntrySet и потоков:

map
  .entrySet()
  .stream()
  .map(e -> e.getKey() + "=" + e.getValue())
  .collect(Collectors.joining("&"));
0 голосов
/ 19 июня 2019

Лично я бы пошел на такое решение, оно невероятно похоже на решение, предоставляемое @rzwitserloot, только с небольшими отличиями.

Это маленькое, простое и чистое решение, требующее очень мало с точки зрения зависимостей, которые являются частью пакета Java Util.

Map<String, String> map = new HashMap<>();

map.put("param1", "12");
map.put("param2", "cat");

String output = "someUrl?";
output += map.entrySet()
    .stream()
    .map(x -> x.getKey() + "=" + x.getValue() + "&")
    .collect(Collectors.joining("&"));

System.out.println(output.substring(0, output.length() -1));
...