지도를 URL 쿼리 문자열로 변환하는 방법은 무엇입니까?
Map을 URL 친화적 인 쿼리 문자열로 변환 할 수있는 유틸리티 클래스 / 라이브러리를 알고 있습니까?
예:
지도가 있습니다.
"param1"=12,
"param2"="cat"
난 갖길 원해:
param1=12¶m2=cat
최종 출력
relativeUrl+param1=12¶m2=cat
내가 기성품으로 본 가장 강력한 것은 Apache Http Compoments (HttpClient 4.0) 의 URLEncodedUtils 클래스입니다 .
그 방법 URLEncodedUtils.format()
은 당신이 필요로하는 것입니다.
맵을 사용하지 않으므로 매개 변수 이름이 중복 될 수 있습니다.
a=1&a=2&b=3
이런 종류의 매개 변수 이름 사용을 권장하지 않습니다.
여기 제가 빠르게 썼던 것이 있습니다. 개선 될 수 있다고 확신합니다.
import java.util.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class MapQuery {
static String urlEncodeUTF8(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
static String urlEncodeUTF8(Map<?,?> map) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<?,?> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(String.format("%s=%s",
urlEncodeUTF8(entry.getKey().toString()),
urlEncodeUTF8(entry.getValue().toString())
));
}
return sb.toString();
}
public static void main(String[] args) {
Map<String,Object> map = new HashMap<String,Object>();
map.put("p1", 12);
map.put("p2", "cat");
map.put("p3", "a & b");
System.out.println(urlEncodeUTF8(map));
// prints "p3=a+%26+b&p2=cat&p1=12"
}
}
Java 8 및 polygenelubricants의 솔루션을 사용하여 부드러운 솔루션을 찾았습니다.
parameters.entrySet().stream()
.map(p -> urlEncodeUTF8(p.getKey()) + "=" + urlEncodeUTF8(p.getValue()))
.reduce((p1, p2) -> p1 + "&" + p2)
.orElse("");
Spring Util에는 더 나은 방법이 있습니다 ..,
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("key", key);
params.add("storeId", storeId);
params.add("orderId", orderId);
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("http://spsenthil.com/order").queryParams(params).build();
ListenableFuture<ResponseEntity<String>> responseFuture = restTemplate.getForEntity(uriComponents.toUriString(), String.class);
2016 년 6 월 업데이트
매우 일반적인 문제에 대해 날짜가 지났거나 부적절한 답변과 함께 너무 많은 SOF 답변을 본 답변을 추가해야한다는 느낌이 들었습니다. 좋은 라이브러리와 parse
및 format
작업 모두에 대한 확실한 예제 사용입니다 .
org.apache.httpcomponents.httpclient 라이브러리를 사용하십시오 . 라이브러리에는이 org.apache.http.client.utils.URLEncodedUtils 클래스 유틸리티 가 포함되어 있습니다 .
예를 들어 Maven에서이 종속성을 쉽게 다운로드 할 수 있습니다.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
내 목적을 위해 parse
(쿼리 문자열에서 이름-값 쌍으로 format
읽기 ) 및 ( 이름-값 쌍에서 쿼리 문자열로 읽기) 쿼리 문자열 만 필요했습니다 . 그러나 URI를 사용하여 동일한 작업을 수행 할 수 있습니다 (아래 주석 처리 된 줄 참조).
// 필수 가져 오기
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
// 코드 스 니펫
public static void parseAndFormatExample() throws UnsupportedEncodingException {
final String queryString = "nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk";
System.out.println(queryString);
// => nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk
final List<NameValuePair> params =
URLEncodedUtils.parse(queryString, StandardCharsets.UTF_8);
// List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), "UTF-8");
for (final NameValuePair param : params) {
System.out.println(param.getName() + " : " + param.getValue());
// => nonce : 12345
// => redirectCallbackUrl : http://www.bbc.co.uk
}
final String newQueryStringEncoded =
URLEncodedUtils.format(params, StandardCharsets.UTF_8);
// decode when printing to screen
final String newQueryStringDecoded =
URLDecoder.decode(newQueryStringEncoded, StandardCharsets.UTF_8.toString());
System.out.println(newQueryStringDecoded);
// => nonce=12345&redirectCallbackUrl=http://www.bbc.co.uk
}
이 라이브러리는 내가 필요한 작업을 정확히 수행했으며 일부 해킹 된 사용자 지정 코드를 대체 할 수있었습니다.
실제로 완전한 URI를 빌드하려면 Apache Http Compoments (HttpClient 4) 에서 URIBuilder 를 사용해보십시오 .
이것은 실제로 질문에 대한 대답은 아니지만이 질문을 발견했을 때 가지고 있던 질문에 대답했습니다.
Java 8 매핑 및 축소를 사용하여 @eclipse의 답변을 구축하고 싶었습니다.
protected String formatQueryParams(Map<String, String> params) {
return params.entrySet().stream()
.map(p -> p.getKey() + "=" + p.getValue())
.reduce((p1, p2) -> p1 + "&" + p2)
.map(s -> "?" + s)
.orElse("");
}
추가 map
연산은 축소 된 문자열을 취하고 ?
문자열이 존재하는 경우에만 앞에를 넣습니다 .
다른 '하나의 클래스'/ 종속성없는 단일 / 다중 처리 :
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class UrlQueryString {
private static final String DEFAULT_ENCODING = "UTF-8";
public static String buildQueryString(final LinkedHashMap<String, Object> map) {
try {
final Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator();
final StringBuilder sb = new StringBuilder(map.size() * 8);
while (it.hasNext()) {
final Map.Entry<String, Object> entry = it.next();
final String key = entry.getKey();
if (key != null) {
sb.append(URLEncoder.encode(key, DEFAULT_ENCODING));
sb.append('=');
final Object value = entry.getValue();
final String valueAsString = value != null ? URLEncoder.encode(value.toString(), DEFAULT_ENCODING) : "";
sb.append(valueAsString);
if (it.hasNext()) {
sb.append('&');
}
} else {
// Do what you want...for example:
assert false : String.format("Null key in query map: %s", map.entrySet());
}
}
return sb.toString();
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
public static String buildQueryStringMulti(final LinkedHashMap<String, List<Object>> map) {
try {
final StringBuilder sb = new StringBuilder(map.size() * 8);
for (final Iterator<Entry<String, List<Object>>> mapIterator = map.entrySet().iterator(); mapIterator.hasNext();) {
final Entry<String, List<Object>> entry = mapIterator.next();
final String key = entry.getKey();
if (key != null) {
final String keyEncoded = URLEncoder.encode(key, DEFAULT_ENCODING);
final List<Object> values = entry.getValue();
sb.append(keyEncoded);
sb.append('=');
if (values != null) {
for (final Iterator<Object> listIt = values.iterator(); listIt.hasNext();) {
final Object valueObject = listIt.next();
sb.append(valueObject != null ? URLEncoder.encode(valueObject.toString(), DEFAULT_ENCODING) : "");
if (listIt.hasNext()) {
sb.append('&');
sb.append(keyEncoded);
sb.append('=');
}
}
}
if (mapIterator.hasNext()) {
sb.append('&');
}
} else {
// Do what you want...for example:
assert false : String.format("Null key in query map: %s", map.entrySet());
}
}
return sb.toString();
} catch (final UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
public static void main(final String[] args) {
// Examples: could be turned into unit tests ...
{
final LinkedHashMap<String, Object> queryItems = new LinkedHashMap<String, Object>();
queryItems.put("brand", "C&A");
queryItems.put("count", null);
queryItems.put("misc", 42);
final String buildQueryString = buildQueryString(queryItems);
System.out.println(buildQueryString);
}
{
final LinkedHashMap<String, List<Object>> queryItems = new LinkedHashMap<String, List<Object>>();
queryItems.put("usernames", new ArrayList<Object>(Arrays.asList(new String[] { "bob", "john" })));
queryItems.put("nullValue", null);
queryItems.put("misc", new ArrayList<Object>(Arrays.asList(new Integer[] { 1, 2, 3 })));
final String buildQueryString = buildQueryStringMulti(queryItems);
System.out.println(buildQueryString);
}
}
}
간단한 (대부분의 경우 쓰기가 더 쉬움) 또는 필요할 때 여러 개를 사용할 수 있습니다. 앰퍼샌드를 추가하여 둘 다 결합 할 수 있습니다. 문제가 발견되면 댓글로 알려주세요.
이것은 Java 8 및 org.apache.http.client.URLEncodedUtils
. 맵의 항목을 목록으로 매핑 BasicNameValuePair
한 다음 Apache를 사용 URLEncodedUtils
하여 쿼리 문자열로 변환합니다.
List<BasicNameValuePair> nameValuePairs = params.entrySet().stream()
.map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
URLEncodedUtils.format(nameValuePairs, Charset.forName("UTF-8"));
@eclipse의 답변을 조금 개선하려면 : Javaland에서 요청 매개 변수 맵은 일반적으로 Map<String, String[]>
, a 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);
}
}
이를 위해 Java에 내장 된 것은 없습니다. 하지만 자바는 프로그래밍 언어라서 .. 프로그래밍하자!
map.values().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"))
This gives you "param1=12¶m2=cat". Now we need to join the URL and this bit together. You'd think you can just do: URL + "?" + theAbove
but if the URL already contains a question mark, you have to join it all together with "&" instead. One way to check is to see if there's a question mark in the URL someplace already.
Also, I don't quite know what is in your map. If it's raw stuff, you probably have to safeguard the call to e.getKey()
and e.getValue()
with URLEncoder.encode
or similar.
Yet another way to go is that you take a wider view. Are you trying to append a map's content to a URL, or... are you trying to make an HTTP(S) request from a java process with the stuff in the map as (additional) HTTP params? In the latter case, you can look into an http library like OkHttp which has some nice APIs to do this job, then you can forego any need to mess about with that URL in the first place.
You can use a Stream
for this, but instead of appending query parameters myself I'd use a Uri.Builder
. For example:
final Map<String, String> map = new HashMap<>();
map.put("param1", "cat");
map.put("param2", "12");
final Uri uri =
map.entrySet().stream().collect(
() -> Uri.parse("relativeUrl").buildUpon(),
(builder, e) -> builder.appendQueryParameter(e.getKey(), e.getValue()),
(b1, b2) -> { throw new UnsupportedOperationException(); }
).build();
//Or, if you consider it more readable...
final Uri.Builder builder = Uri.parse("relativeUrl").buildUpon();
map.entrySet().forEach(e -> builder.appendQueryParameter(e.getKey(), e.getValue())
final Uri uri = builder.build();
//...
assertEquals(Uri.parse("relativeUrl?param1=cat¶m2=12"), uri);
Personally, I'd go for a solution like this, it's incredibly similar to the solution provided by @rzwitserloot, only subtle differences.
This solution is small, simple & clean, it requires very little in terms of dependencies, all of which are a part of the Java Util package.
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));
Using EntrySet and Streams:
map
.entrySet()
.stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(Collectors.joining("&"));
I think this is better for memory usage and performance, and I want to send just the property name when the value is null.
public static String toUrlEncode(Map<String, Object> map) {
StringBuilder sb = new StringBuilder();
map.entrySet().stream()
.forEach(entry
-> (entry.getValue() == null
? sb.append(entry.getKey())
: sb.append(entry.getKey())
.append('=')
.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)))
.append('&')
);
sb.delete(sb.length() - 1, sb.length());
return sb.toString();
}
참고URL : https://stackoverflow.com/questions/2809877/how-to-convert-map-to-url-query-string
'development' 카테고리의 다른 글
Bash를 사용하여 각 줄의 마지막 단어를 얻는 방법 (0) | 2020.11.19 |
---|---|
파이프 라인을 작성하여 이전 빌드를 삭제하는 방법은 무엇입니까? (0) | 2020.11.19 |
Visual Studio-프로세스 바로 가기에 연결 (0) | 2020.11.19 |
Android-DataBinding-Binding 클래스는 언제 어떻게 생성됩니까? (0) | 2020.11.19 |
빈 conda 환경 만들기 (0) | 2020.11.19 |