372 Stimmen

Parsen einer URI-Zeichenkette in eine Name-Werte-Sammlung

Ich habe die URI so eingestellt:

https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback

Ich brauche eine Sammlung mit geparsten Elementen:

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

Um genau zu sein, brauche ich ein Java-Äquivalent für die C#/.NET HttpUtility.ParseQueryString Methode.

423voto

Pr0gr4mm3r Punkte 6130

Wenn Sie nach einer Möglichkeit suchen, dies ohne eine externe Bibliothek zu erreichen, wird Ihnen der folgende Code helfen.

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;
}

Sie können auf die zurückgegebene Karte mit <map>.get("client_id") mit der in Ihrer Frage angegebenen URL würde dies "SS" ergeben.

UPDATE URL-Dekodierung hinzugefügt

UPDATE Da diese Antwort immer noch sehr beliebt ist, habe ich eine verbesserte Version der obigen Methode erstellt, die auch mehrere Parameter mit demselben Schlüssel und Parameter ohne Wert behandelt.

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;
}

UPDATE Java8-Version

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<>(
        URLDecoder.decode(key, StandardCharsets.UTF_8),
        URLDecoder.decode(value, StandardCharsets.UTF_8)
    );
}

Ausführen der obigen Methode mit der URL

https://stackoverflow.com?param1=value1&param2=&param3=value3&param3

gibt diese Karte zurück:

{param1=["value1"], param2=[null], param3=["value3", null]}

410voto

Juan Mendes Punkte 85125

org.apache.http.client.utils.URLEncodedUtils

ist eine bekannte Bibliothek, die dies für Sie erledigen kann

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());
}

Ausgänge

one : 1
two : 2
three : 3
three : 3a

167voto

xxg Punkte 1858

Wenn Sie Spring Framework verwenden:

public static void main(String[] args) {
    String uri = "http://my.test.com/test?param1=ab&param2=cd&param2=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));
}

Sie werden bekommen:

param1: ab
param2: cd,ef

60voto

Amin Abbaspour Punkte 1085

Verwenden Sie Google Guava und machen Sie es in 2 Zeilen:

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);
    }
}

die Ihnen

{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}

51voto

Dmitry Senkovich Punkte 5381

Der kürzeste Weg, den ich gefunden habe, ist dieser:

MultiValueMap<String, String> queryParams =
            UriComponentsBuilder.fromUriString(url).build().getQueryParams();

UPDATE: UriComponentsBuilder kommt vom Frühling. Hier die Verbindung .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X