25

In Java I have:

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

I want to get values of depCity parameters (PAR,NYC).

So I created regex:

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

m.find() is returning false. m.groups() is returning IllegalArgumentException.

What am I doing wrong?

1

7 Answers 7

44

It doesn't have to be regex. Since I think there's no standard method to handle this thing, I'm using something that I copied from somewhere (and perhaps modified a bit):

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

So, when you call it, you will get all parameters and their values. The method handles multi-valued params, hence the List<String> rather than String, and in your case you'll need to get the first list element.

Sign up to request clarification or add additional context in comments.

6 Comments

This solution is also working, but personally I'm not a fan of Maps - I try to use solutions that are more simple. But thanks anyway!
Maps are a very core and simple concept, so I don't see an issue with them.
This solution does not regard the fragment part of an URL which is appended on the end after a "#". In http urls this part references an internal anchor. So the variable query must be split again at "#" and then the index 0 of the returned array must be further processed.
the part after # is not submitted to the server
It will raise an ArrayIndexOutOfBoundException for corner cases such as "/foo?="
|
17

Not sure how you used find and group, but this works fine:

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
}

However, If you only want the values, not the key depCity= then you can either use m.group(1) or use a regex with lookarounds:

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

It works in the same Java code as above. It tries to find a start position right after depCity=. Then matches anything but as little as possible until it reaches a point facing & or end of input.

1 Comment

Just a small remark: instead of using complicating pattern "(?<=depCity=).*?(?=&|$)" to get only values, Im using the first soluiton "depCity=([^&]+)" in combination with m.group(1) to get only values.
17

I have three solutions, the third one is an improved version of Bozho's.

First, if you don't want to write stuff yourself and simply use a lib, then use Apache's httpcomponents lib's URIBuilder class: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html

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

Second:

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

Third:

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

2 Comments

"improved version of Bozho's"? That's a sacrilege. :)
I am using Apache Httpclient library, and the 1st solution is very handy.
10

If you are developing an Android application, try this:

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

2 Comments

What library do you use for Uri class?
import android.net.Uri;
8

If spring-web is present on classpath, UriComponentsBuilder can be used.

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

Comments

2

Simple Solution create the map out of all param name and values and use it :).

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

1 Comment

Hint: Add String param = URLDecoder.decode(param , "UTF-8"); inside loop
0

same but with jsonobject:

public static JSONObject getQueryParams2(String url) {
    JSONObject json = new JSONObject();
    try {
        String[] urlParts = url.split("\\?");
        JSONArray array = new  JSONArray();
        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");
                    if(json.has(key)) {
                        array = json.getJSONArray(key);
                        array.put(value);
                        json.put(key, array);
                        array = new JSONArray();
                    } else {
                        array.put(value);
                        json.put(key, array);
                        array = new JSONArray();
                    }
                }
            }
        }
        return json;
    } catch (Exception ex) {
        throw new AssertionError(ex);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.