Ser*_*iev 247 java parsing uri namevaluecollection
我有这样的URI:
https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback
Run Code Online (Sandbox Code Playgroud)
我需要一个带有解析元素的集合:
NAME VALUE
------------------------
client_id SS
response_type code
scope N_FULL
access_type offline
redirect_uri http://localhost/Callback
Run Code Online (Sandbox Code Playgroud)
确切地说,我需要一个Java等价的C#HttpUtility.ParseQueryString方法.请给我一个建议.谢谢.
Pr0*_*m3r 319
如果您正在寻找一种方法来实现它而不使用外部库,以下代码将帮助您.
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;
}
Run Code Online (Sandbox Code Playgroud)
你可以使用<map>.get("client_id")你的问题中给出的URL 来访问返回的Map ,这将返回"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;
}
Run Code Online (Sandbox Code Playgroud)
更新 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);
}
Run Code Online (Sandbox Code Playgroud)
使用URL运行上述方法
https://stackoverflow.com?param1=value1¶m2=¶m3=value3¶m3
返回此地图:
{param1=["value1"], param2=[null], param3=["value3", null]}
Run Code Online (Sandbox Code Playgroud)
Jua*_*des 281
是一个众所周知的图书馆,可以为你做
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());
}
Run Code Online (Sandbox Code Playgroud)
输出
one : 1
two : 2
three : 3
three : 3a
Run Code Online (Sandbox Code Playgroud)
注意:仅适用于HTTP PUT或HTTP POST
xxg*_*xxg 89
如果您使用的是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));
}
Run Code Online (Sandbox Code Playgroud)
你会得到:
param1: ab
param2: cd,ef
Run Code Online (Sandbox Code Playgroud)
小智 48
使用谷歌番石榴,并在2行中完成:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
给你的
{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}
Run Code Online (Sandbox Code Playgroud)
Dmi*_*ich 25
我找到的最短路是这一个:
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUriString(url).build().getQueryParams();
Run Code Online (Sandbox Code Playgroud)
更新: UriComponentsBuilder来自Spring.这里的链接.
THA*_*rum 14
对于Android,如果您在项目中使用OkHttp.你可以看看这个.它简单而有帮助.
final HttpUrl url = HttpUrl.parse(query);
if (url != null) {
final String target = url.queryParameter("target");
final String id = url.queryParameter("id");
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用Java 8并且您愿意编写一些可重用的方法,则可以在一行中完成.
private Map<String, List<String>> parse(final String query) {
return Arrays.asList(query.split("&")).stream().map(p -> p.split("=")).collect(Collectors.toMap(s -> decode(index(s, 0)), s -> Arrays.asList(decode(index(s, 1))), this::mergeLists));
}
private <T> List<T> mergeLists(final List<T> l1, final List<T> l2) {
List<T> list = new ArrayList<>();
list.addAll(l1);
list.addAll(l2);
return list;
}
private static <T> T index(final T[] array, final int index) {
return index >= array.length ? null : array[index];
}
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);
}
}
Run Code Online (Sandbox Code Playgroud)
但这是一个非常残酷的路线.
给出要分析的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");
Run Code Online (Sandbox Code Playgroud)
此解决方案收集对的列表:
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());
Run Code Online (Sandbox Code Playgroud)
另一方面,该解决方案收集地图(假设在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())));
Run Code Online (Sandbox Code Playgroud)
两种解决方案都必须使用效用函数来正确解码参数.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你正在使用servlet doGet试试这个
request.getParameterMap()
Run Code Online (Sandbox Code Playgroud)
返回此请求的参数的java.util.Map.
返回:一个不可变的java.util.Map,包含作为键的参数名称和作为映射值的参数值.参数映射中的键是String类型.参数映射中的值是String数组类型.
(Java doc)
在 Android 上,包android.net 中有一个 Uri 类。请注意,Uri是android.net 的一部分,而URI是java.net 的一部分。
以下函数以HashMap的形式返回键值对。
在 Java 中:
Map<String, String> getQueryKeyValueMap(Uri uri){
HashMap<String, String> keyValueMap = new HashMap();
String key;
String value;
Set<String> keyNamesList = uri.getQueryParameterNames();
Iterator iterator = keyNamesList.iterator();
while (iterator.hasNext()){
key = (String) iterator.next();
value = uri.getQueryParameter(key);
keyValueMap.put(key, value);
}
return keyValueMap;
}
Run Code Online (Sandbox Code Playgroud)
在科特林:
fun getQueryKeyValueMap(uri: Uri): HashMap<String, String> {
val keyValueMap = HashMap<String, String>()
var key: String
var value: String
val keyNamesList = uri.queryParameterNames
val iterator = keyNamesList.iterator()
while (iterator.hasNext()) {
key = iterator.next() as String
value = uri.getQueryParameter(key) as String
keyValueMap.put(key, value)
}
return keyValueMap
}
Run Code Online (Sandbox Code Playgroud)
Netty还提供了一个很好的查询字符串解析器,称为QueryStringDecoder. 在一行代码中,它可以解析问题中的 URL。我喜欢,因为它不需要捕捉或投掷java.net.MalformedURLException。
在一行中:
Map<String, List<String>> parameters = new QueryStringDecoder(url).parameters();
Run Code Online (Sandbox Code Playgroud)
请参阅此处的 javadoc:https : //netty.io/4.1/api/io/netty/handler/codec/http/QueryStringDecoder.html
这是一个简短的、自包含的、正确的示例:
import io.netty.handler.codec.http.QueryStringDecoder;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
public class UrlParse {
public static void main(String... args) {
String url = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
QueryStringDecoder decoder = new QueryStringDecoder(url);
Map<String, List<String>> parameters = decoder.parameters();
print(parameters);
}
private static void print(final Map<String, List<String>> parameters) {
System.out.println("NAME VALUE");
System.out.println("------------------------");
parameters.forEach((key, values) ->
values.forEach(val ->
System.out.println(StringUtils.rightPad(key, 19) + val)));
}
}
Run Code Online (Sandbox Code Playgroud)
这产生
NAME VALUE
------------------------
client_id SS
response_type code
scope N_FULL
access_type offline
redirect_uri http://localhost/Callback
Run Code Online (Sandbox Code Playgroud)
Apache HTTP 客户端有一个新版本 - org.apache.httpcomponents.client5-URLEncodedUtils现已弃用。URIBuilder应该使用:
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.net.URIBuilder;
private static Map<String, String> getQueryParameters(final String url) throws URISyntaxException {
return new URIBuilder(new URI(url), StandardCharsets.UTF_8).getQueryParams()
.stream()
.collect(Collectors.toMap(NameValuePair::getName,
nameValuePair -> URLDecoder.decode(nameValuePair.getValue(), StandardCharsets.UTF_8)));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
282958 次 |
| 最近记录: |