web-dev-qa-db-fra.com

Comment extraire des paramètres d'une URL donnée

Dans Java j'ai:

String params = "depCity=PAR&roomType=D&depCity=NYC";

Je veux obtenir les valeurs des paramètres depCity (PAR, NYC).

J'ai donc créé regex:

String regex = "depCity=([^&]+)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(params);

m.find() retourne false. m.groups() renvoie IllegalArgumentException.

Qu'est-ce que je fais mal?

19
gospodin

Il n'est pas nécessaire que ce soit regex. Comme je pense qu'il n'y a pas de méthode standard pour gérer cette chose, j'utilise quelque chose que j'ai copié quelque part (et peut-être un peu modifié):

public static Map<String, List<String>> getQueryParams(String url) {
    try {
        Map<String, List<String>> params = new HashMap<String, List<String>>();
        String[] urlParts = url.split("\\?");
        if (urlParts.length > 1) {
            String query = urlParts[1];
            for (String param : query.split("&")) {
                String[] pair = param.split("=");
                String key = URLDecoder.decode(pair[0], "UTF-8");
                String value = "";
                if (pair.length > 1) {
                    value = URLDecoder.decode(pair[1], "UTF-8");
                }

                List<String> values = params.get(key);
                if (values == null) {
                    values = new ArrayList<String>();
                    params.put(key, values);
                }
                values.add(value);
            }
        }

        return params;
    } catch (UnsupportedEncodingException ex) {
        throw new AssertionError(ex);
    }
}

Ainsi, lorsque vous l'appelez, vous obtiendrez tous les paramètres et leurs valeurs. La méthode gère les paramètres à valeurs multiples, d'où le List<String> plutôt que String, et dans votre cas, vous devrez obtenir le premier élément de la liste.

39
Bozho

Je ne sais pas comment vous avez utilisé find et group, mais cela fonctionne très bien:

String params = "depCity=PAR&roomType=D&depCity=NYC";

try {
    Pattern p = Pattern.compile("depCity=([^&]+)");
    Matcher m = p.matcher(params);
    while (m.find()) {
        System.out.println(m.group());
    } 
} catch (PatternSyntaxException ex) {
    // error handling
}

Cependant, si vous ne voulez que les valeurs, pas la clé depCity=, Vous pouvez soit utiliser m.group(1) soit utiliser une expression régulière avec des contournements:

Pattern p = Pattern.compile("(?<=depCity=).*?(?=&|$)");

Il fonctionne dans le même code Java comme ci-dessus. Il essaie de trouver une position de départ juste après depCity=. Correspond ensuite à tout mais aussi peu que possible jusqu'à ce qu'il atteigne un point face à & Ou fin de saisie.

14

Si vous développez une application Android Android, essayez ceci:

String yourParam = null;
 Uri uri = Uri.parse(url);
        try {
            yourParam = URLDecoder.decode(uri.getQueryParameter(PARAM_NAME), "UTF-8");
        } catch (UnsupportedEncodingException exception) {
            exception.printStackTrace();
        }
8
Waran-

J'ai trois solutions, la troisième est une version améliorée de Bozho.

Tout d'abord, si vous ne voulez pas écrire vous-même et utiliser simplement une lib, utilisez la classe URIBuilder de lib de httpcomponents d'Apache: http://hc.Apache.org/httpcomponents-client-ga/httpclient/apidocs/ org/Apache/http/client/utils/URIBuilder.html

new URIBuilder("http://...").getQueryParams()...

Seconde:

// overwrites duplicates
import org.Apache.http.NameValuePair;
import org.Apache.http.client.utils.URLEncodedUtils;
public static Map<String, String> readParamsIntoMap(String url, String charset) throws URISyntaxException {
    Map<String, String> params = new HashMap<>();

    List<NameValuePair> result = URLEncodedUtils.parse(new URI(url), charset);

    for (NameValuePair nvp : result) {
        params.put(nvp.getName(), nvp.getValue());
    }

    return params;
}

Troisième:

public static Map<String, List<String>> getQueryParams(String url) throws UnsupportedEncodingException {
    Map<String, List<String>> params = new HashMap<String, List<String>>();
    String[] urlParts = url.split("\\?");
    if (urlParts.length < 2) {
        return params;
    }

    String query = urlParts[1];
    for (String param : query.split("&")) {
        String[] pair = param.split("=");
        String key = URLDecoder.decode(pair[0], "UTF-8");
        String value = "";
        if (pair.length > 1) {
            value = URLDecoder.decode(pair[1], "UTF-8");
        }

        // skip ?& and &&
        if ("".equals(key) && pair.length == 1) {
            continue;
        }

        List<String> values = params.get(key);
        if (values == null) {
            values = new ArrayList<String>();
            params.put(key, values);
        }
        values.add(value);
    }

    return params;
}
7
user1050755

Si spring-web est présent sur classpath, riComponentsBuilder peut être utilisé.

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

Solution simple créez la carte à partir de tous les noms et valeurs de paramètres et utilisez-la :).

import org.Apache.commons.lang3.StringUtils;

    public String splitURL(String url, String parameter){
                HashMap<String, String> urlMap=new HashMap<String, String>();
                String queryString=StringUtils.substringAfter(url,"?");
                for(String param : queryString.split("&")){
                    urlMap.put(StringUtils.substringBefore(param, "="),StringUtils.substringAfter(param, "="));
                }
                return urlMap.get(parameter);
            }
2
manish Prasad