views:

301

answers:

3

Do you know of any utility class/library, that can convert Map into URL-friendly query string?

Example:
I have a map:
- "param1"=12,
- "param2"="cat"

I want to get: param1=12&param2=cat.

PS. I know I can easily write it myself, I am just surprised that I cannot find it anywhere (I checked Apache Commons so far).

A: 

Here's something that I quickly wrote; I'm sure it can be improved upon.

import java.util.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class MapQuery {
    static String urlEncodeUTF8(String s) {
        try {
            return URLEncoder.encode(s, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException(e);
        }
    }
    static String urlEncodeUTF8(Map<?,?> map) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?,?> entry : map.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(String.format("%s=%s",
                urlEncodeUTF8(entry.getKey().toString()),
                urlEncodeUTF8(entry.getValue().toString())
            ));
        }
        return sb.toString();       
    }
    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("p1", 12);
        map.put("p2", "cat");
        map.put("p3", "a & b");         
        System.out.println(urlEncodeUTF8(map));
        // prints "p3=a+%26+b&p2=cat&p1=12"
    }
}
polygenelubricants
Key needs to be encoded too.
ZZ Coder
Writing your own isn't difficult, the question is where, if anywhere, is there an off-the-shelf version.
skaffman
@ZZCoder: Yeah, I was wondering about that. Anything else? I'll do mass update on next revision based on suggestions.
polygenelubricants
@skaffman: Yeah, I saw that later after I wrote it, but anyway, now that I already did, I might as well use this opportunity to have other people review my code and improve it etc. If not for OP, it'll still benefit me, and perhaps some others too.
polygenelubricants
The parametermap is **usually** represented as `Map<String, List<String>>` or `Map<String, String[]>`. You can namely have multiple values for the same name. Not sure if OP was smart to design it that way.
BalusC
@BalusC: thanks for info. By the way, how should this (if it were written for a library) handle `null` keys/values? Right now the `toString()` causes `NullPointerException`, and I justify it by saying "fail-fast", but I'm not sure how that would go with people who just wants things to "work".
polygenelubricants
Only values are allowed to be empty (I'd insert a `""`). NPE's on keys however, I would just document it and let them go. It's developer's fault.
BalusC
A: 

The first method here.

Bozho
But as with http://stackoverflow.com/questions/2809877/how-to-convert-map-to-url-query-string/2810102#2810102, this isn't exactly an off-the-shelf version out of a well-known lib.
Jonik
+2  A: 

The most robust one I saw off-shelf is the URLEncodedUtils class from Apache Http Compoments (HttpClient 4.0).

The method URLEncodeUtils.format() is what you need.

It doesn't use map so you can have duplicate parameter names, like,

  a=1&a=2&b=3

Not that I recommend this kind of use of parameter names.

ZZ Coder
It's close to what I need. The only problem is it requires NameValuePair objects and what I have are Map.Entry objects at best.
Ula Krukar
@Ula: You could use this and do `Collections2.transform(paramMap.entrySet(), function)` where function takes a Map.Entry and returns BasicNameValuePair. (Or do the same in plain old Java without Google Collections.) Granted, about 6 extra lines of own code needed.
Jonik
@Jonik, that is exactly what I will do :) But still I am surprised that there is nothing that simply takes a Map, seems so obvious that there should. There is lots of methods that turn query string into a map and nothing that does the opposite.
Ula Krukar