How to parse an URL query string

A Java servlet program can use ServletRequest.getParameterMap() to parse the query string of the URL that has been used to invoke the servlet. But there is no (non-deprecated) routine in the current Java SE/EE libraries to parse an arbitrary URL query string. The routine parseUrlQueryString() below may be used to do that.

Download: TestParseUrlQueryString.java (includes some small test code)




/**
* Parses an URL query string and returns a map with the parameter values.
* The URL query string is the part in the URL after the first '?' character up
* to an optional '#' character. It has the format "name=value&name=value&...".
* The map has the same structure as the one returned by
* javax.servlet.ServletRequest.getParameterMap().
* A parameter name may occur multiple times within the query string.
* For each parameter name, the map contains a string array with the parameter values.
* @param  s  an URL query string.
* @return    a map containing parameter names as keys and parameter values as map values.
* @author    Christian d'Heureuse, Inventec Informatik AG, Switzerland, www.source-code.biz.
*/
public static Map<String, String[]> parseUrlQueryString (String s) {
   if (s == null) return new HashMap<String, String[]>(0);
   // In map1 we use strings and ArrayLists to collect the parameter values.
   HashMap<String, Object> map1 = new HashMap<String, Object>();
   int p = 0;
   while (p < s.length()) {
      int p0 = p;
      while (p < s.length() && s.charAt(p) != '=' && s.charAt(p) != '&') p++;
      String name = urlDecode(s.substring(p0, p));
      if (p < s.length() && s.charAt(p) == '=') p++;
      p0 = p;
      while (p < s.length() && s.charAt(p) != '&') p++;
      String value = urlDecode(s.substring(p0, p));
      if (p < s.length() && s.charAt(p) == '&') p++;
      Object x = map1.get(name);
      if (x == null) {
         // The first value of each name is added directly as a string to the map.
         map1.put (name, value); }
       else if (x instanceof String) {
         // For multiple values, we use an ArrayList.
         ArrayList<String> a = new ArrayList<String>();
         a.add ((String)x);
         a.add (value);
         map1.put (name, a); }
       else {
         @SuppressWarnings("unchecked")
            ArrayList<String> a = (ArrayList<String>)x;
         a.add (value); }}
   // Copy map1 to map2. Map2 uses string arrays to store the parameter values.
   HashMap<String, String[]> map2 = new HashMap<String, String[]>(map1.size());
   for (Map.Entry<String, Object> e : map1.entrySet()) {
      String name = e.getKey();
      Object x = e.getValue();
      String[] v;
      if (x instanceof String) {
         v = new String[]{(String)x}; }
       else {
         @SuppressWarnings("unchecked")
            ArrayList<String> a = (ArrayList<String>)x;
         v = new String[a.size()];
         v = a.toArray(v); }
      map2.put (name, v); }
   return map2; }

private static String urlDecode (String s) {
   try {
      return URLDecoder.decode(s, "UTF-8"); }
    catch (UnsupportedEncodingException e) {
      throw new RuntimeException("Error in urlDecode.", e); }}


Author: Christian d'Heureuse (www.source-code.biz, www.inventec.ch/chdh)
License: Free
Index