[java] URI 문자열을 이름-값 컬렉션으로 구문 분석
다음과 같은 URI가 있습니다.
https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback
구문 분석 된 요소가있는 컬렉션이 필요합니다.
NAME VALUE
------------------------
client_id SS
response_type code
scope N_FULL
access_type offline
redirect_uri http://localhost/Callback
정확히 말하면 C # /. NET HttpUtility.ParseQueryString 메서드에 해당하는 Java가 필요합니다 .
제발, 이것에 대한 조언을 해주세요.
감사.
답변
외부 라이브러리를 사용하지 않고 달성 할 수있는 방법을 찾고 있다면 다음 코드가 도움이 될 것입니다.
public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException {
Map<String, String> query_pairs = new LinkedHashMap<String, String>();
String query = url.getQuery();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
return query_pairs;
}
를 사용하여 반환 된지도에 액세스 할 수 있습니다. <map>.get("client_id")
질문에 제공된 URL을 사용 하면 “SS”가 반환됩니다.
업데이트 URL 디코딩 추가
업데이트이 답변은 여전히 인기이므로 위의 방법의 향상된 버전을 만들었습니다.이 방법은 동일한 키로 여러 매개 변수를 처리하고 값이없는 매개 변수도 처리합니다.
public static Map<String, List<String>> splitQuery(URL url) throws UnsupportedEncodingException {
final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
final String[] pairs = url.getQuery().split("&");
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
if (!query_pairs.containsKey(key)) {
query_pairs.put(key, new LinkedList<String>());
}
final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
query_pairs.get(key).add(value);
}
return query_pairs;
}
Java8 버전 업데이트
public Map<String, List<String>> splitQuery(URL url) {
if (Strings.isNullOrEmpty(url.getQuery())) {
return Collections.emptyMap();
}
return Arrays.stream(url.getQuery().split("&"))
.map(this::splitQueryParameter)
.collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, mapping(Map.Entry::getValue, toList())));
}
public SimpleImmutableEntry<String, String> splitQueryParameter(String it) {
final int idx = it.indexOf("=");
final String key = idx > 0 ? it.substring(0, idx) : it;
final String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
return new SimpleImmutableEntry<>(key, value);
}
URL로 위의 메소드 실행
https://stackoverflow.com?param1=value1¶m2=¶m3=value3¶m3
이지도를 반환합니다 :
{param1=["value1"], param2=[null], param3=["value3", null]}
답변
org.apache.http.client.utils.URLEncodedUtils
당신을 위해 그것을 할 수있는 잘 알려진 라이브러리입니다
import org.apache.hc.client5.http.utils.URLEncodedUtils
String url = "http://www.example.com/something.html?one=1&two=2&three=3&three=3a";
List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8"));
for (NameValuePair param : params) {
System.out.println(param.getName() + " : " + param.getValue());
}
출력
one : 1
two : 2
three : 3
three : 3a
답변
Spring Framework를 사용하는 경우 :
public static void main(String[] args) {
String uri = "http://my.test.com/test?param1=ab¶m2=cd¶m2=ef";
MultiValueMap<String, String> parameters =
UriComponentsBuilder.fromUriString(uri).build().getQueryParams();
List<String> param1 = parameters.get("param1");
List<String> param2 = parameters.get("param2");
System.out.println("param1: " + param1.get(0));
System.out.println("param2: " + param2.get(0) + "," + param2.get(1));
}
당신은 얻을 것이다 :
param1: ab
param2: cd,ef
답변
구글 구아바를 사용하고 두 줄로하십시오 :
import java.util.Map;
import com.google.common.base.Splitter;
public class Parser {
public static void main(String... args) {
String uri = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
String query = uri.split("\\?")[1];
final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(query);
System.out.println(map);
}
}
너에게주는
{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}
답변
내가 찾은 가장 짧은 방법은 다음과 같습니다.
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUriString(url).build().getQueryParams();
업데이트 : UriComponentsBuilder
봄에서 온다. 여기 에 링크가 있습니다.
답변
Android의 경우 프로젝트에서 OkHttp 를 사용하는 경우 당신은 이것을 볼 수 있습니다. 간단하고 도움이됩니다.
final HttpUrl url = HttpUrl.parse(query);
if (url != null) {
final String target = url.queryParameter("target");
final String id = url.queryParameter("id");
}
답변
자바 8 원문
분석 할 URL이 주어지면 :
URL url = new URL("https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback");
이 솔루션은 쌍의 목록을 수집합니다.
List<AbstractMap.SimpleEntry<String, String>> list =
Pattern.compile("&").splitAsStream(url.getQuery())
.map(s -> Arrays.copyOf(s.split("="), 2))
.map(o -> new AbstractMap.SimpleEntry<String, String>(decode(o[0]), decode(o[1])))
.collect(toList());
반면 에이 솔루션은 맵을 수집합니다 (URL에는 이름은 같지만 값이 다른 매개 변수가 더 많을 수 있음).
Map<String, List<String>> list =
Pattern.compile("&").splitAsStream(url.getQuery())
.map(s -> Arrays.copyOf(s.split("="), 2))
.collect(groupingBy(s -> decode(s[0]), mapping(s -> decode(s[1]), toList())));
두 솔루션 모두 유틸리티 기능을 사용하여 매개 변수를 올바르게 디코딩해야합니다.
private static String decode(final String encoded) {
try {
return encoded == null ? null : URLDecoder.decode(encoded, "UTF-8");
} catch(final UnsupportedEncodingException e) {
throw new RuntimeException("Impossible: UTF-8 is a required encoding", e);
}
}