Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any Java equivalent of PHP's http_build_query function?

Tags:

java

http

php

build

I have a Map with my data and want to build a query string with it, just like I would with http_build_query on PHP. I'm not sure if this code is the best implementation of it or if I'm forgetting something?

public String toQueryString(Map<?, ?> data) throws UnsupportedEncodingException {
    StringBuffer queryString = new StringBuffer();

    for (Entry<?, ?> pair : data.entrySet()) {
        queryString.append ( URLEncoder.encode ( (String) pair.getKey (), "UTF-8" ) + "=" );
        queryString.append ( URLEncoder.encode ( (String) pair.getValue (), "UTF-8" ) + "&" );
    }

    if (queryString.length () > 0) {
        queryString.deleteCharAt ( queryString.length () - 1 );
    }

    return queryString.toString ();
}
like image 429
falmp Avatar asked Mar 11 '09 23:03

falmp


People also ask

What does http_ build_ query do?

The http_build_query() function is an inbuilt function in PHP which is used to generate URL-encoded query string from the associative (or indexed) array.

What is the role of query string in web communication write an example for a query string?

A query string commonly includes fields added to a base URL by a Web browser or other client application, for example as part of an HTML, choosing the appearance of a page, or jumping to positions in multimedia content.

What is Query String PHP?

A query string is a term for adding/passing data in the URL. It is not language specific.


4 Answers

You'd probably want to check the "Accept" request header for the encodings supported by the client before forcing UTF-8 (even though it's probably the best choice).

like image 41
gmw Avatar answered Oct 18 '22 21:10

gmw


look at the QueryStringBuilder class and its test class :

private String httpBuildQuery(Map<String, String> data)
        throws UnsupportedEncodingException {
    QueryStringBuilder builder = new QueryStringBuilder();
    for (Entry<String, String> pair : data.entrySet()) {
        builder.addQueryParameter(pair.getKey(), pair.getValue());
    }
    return builder.encode("UTF-8");
}
like image 198
Vladimir Avatar answered Oct 18 '22 21:10

Vladimir


The true power of PHP http_build_query function is its ability to get associative array and translate it into URL string. The following code do similar thing and it allows url params to be constructed as multi level Map that include nested Map and Collections.With some more work this a support for Array can also be added.

Test methods are shown below.

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

 /**
 * Class: URLBuilder
 * User: Gilad Tiram
 * Date: 6/12/13
 * Time: 4:02 PM
 * <p/>
 * <p/>
 * Utility that helps to build URL String
 */
 public class URLBuilder {


/**
 * Build URL string from Map of params. Nested Map and Collection is also supported
 *
 * @param params   Map of params for constructing the URL Query String
 * @param encoding encoding type. If not set the "UTF-8" is selected by default
 * @return String of type key=value&...key=value
 * @throws java.io.UnsupportedEncodingException
 *          if encoding isnot supported
 */
public static String httpBuildQuery(Map<String, Object> params, String encoding) {
    if (isEmpty(encoding)) {
        encoding = "UTF-8";
    }
    StringBuilder sb = new StringBuilder();
    for (Map.Entry<String, Object> entry : params.entrySet()) {
        if (sb.length() > 0) {
            sb.append('&');
        }

        String name = entry.getKey();
        Object value = entry.getValue();


        if (value instanceof Map) {
            List<String> baseParam = new ArrayList<String>();
            baseParam.add(name);
            String str = buildUrlFromMap(baseParam, (Map) value, encoding);
            sb.append(str);

        } else if (value instanceof Collection) {
            List<String> baseParam = new ArrayList<String>();
            baseParam.add(name);
            String str = buildUrlFromCollection(baseParam, (Collection) value, encoding);
            sb.append(str);

        } else {
            sb.append(encodeParam(name));
            sb.append("=");
            sb.append(encodeParam(value));
        }


    }
    return sb.toString();
}

private static String buildUrlFromMap(List<String> baseParam, Map<Object, Object> map, String encoding) {
    StringBuilder sb = new StringBuilder();
    String token;

    //Build string of first level - related with params of provided Map
    for (Map.Entry<Object, Object> entry : map.entrySet()) {

        if (sb.length() > 0) {
            sb.append('&');
        }

        String name = String.valueOf(entry.getKey());
        Object value = entry.getValue();
        if (value instanceof Map) {
            List<String> baseParam2 = new ArrayList<String>(baseParam);
            baseParam2.add(name);
            String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
            sb.append(str);

        } else if (value instanceof List) {
            List<String> baseParam2 = new ArrayList<String>(baseParam);
            baseParam2.add(name);
            String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
            sb.append(str);
        } else {
            token = getBaseParamString(baseParam) + "[" + name + "]=" + encodeParam(value);
            sb.append(token);
        }
    }

    return sb.toString();
}

private static String buildUrlFromCollection(List<String> baseParam, Collection coll, String encoding) {
    StringBuilder sb = new StringBuilder();
    String token;
    if (!(coll instanceof List)) {
        coll = new ArrayList(coll);
    }
    List arrColl = (List) coll;

    //Build string of first level - related with params of provided Map
    for (int i = 0; i < arrColl.size(); i++) {

        if (sb.length() > 0) {
            sb.append('&');
        }

        Object value = (Object) arrColl.get(i);
        if (value instanceof Map) {
            List<String> baseParam2 = new ArrayList<String>(baseParam);
            baseParam2.add(String.valueOf(i));
            String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
            sb.append(str);

        } else if (value instanceof List) {
            List<String> baseParam2 = new ArrayList<String>(baseParam);
            baseParam2.add(String.valueOf(i));
            String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
            sb.append(str);
        } else {
            token = getBaseParamString(baseParam) + "[" + i + "]=" + encodeParam(value);
            sb.append(token);
        }
    }

    return sb.toString();
}


private static String getBaseParamString(List<String> baseParam) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < baseParam.size(); i++) {
        String s = baseParam.get(i);
        if (i == 0) {
            sb.append(s);
        } else {
            sb.append("[" + s + "]");
        }
    }
    return sb.toString();
}

/**
 * Check if String is either empty or null
 *
 * @param str string to check
 * @return true if string is empty. Else return false
 */
public static boolean isEmpty(String str) {
    return str == null || str.length() == 0;
}


private static String encodeParam(Object param) {
    try {
        return URLEncoder.encode(String.valueOf(param), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return URLEncoder.encode(String.valueOf(param));
    }
}

/* ========================================================================= */
/* Test functions                                                            */
/* ========================================================================= */


public static void main(String[] args) {
    //basicTest();
    //testWithMap();
    //testWithList();
    //testWithNestedMap();
    //testWithNestedList();
    testCompound();
}

private static void basicTest() {
    Map<String, Object> params = new LinkedHashMap<String, Object>();
    params.put("a", "1");
    params.put("b", "2");
    params.put("c", "3");

    System.out.println(httpBuildQuery(params, "UTF-8"));
}

private static void testWithMap() {
    Map<String, Object> params = new LinkedHashMap<String, Object>();
    params.put("a", "1");
    params.put("b", "2");

    Map<String, Object> cParams = new LinkedHashMap<String, Object>();
    cParams.put("c1", "c1val");
    cParams.put("c2", "c2val");
    params.put("c", cParams);

    System.out.println(httpBuildQuery(params, "UTF-8"));
}

private static void testWithNestedMap() {
    Map<String, Object> params = new LinkedHashMap<String, Object>();
    params.put("a", "1");
    params.put("b", "2");

    Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
    cParamsLevel1.put("cL1-1", "cLevel1-1val");
    cParamsLevel1.put("cL1-2", "cLevel1-2val");

    Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
    cParamsLevel2.put("cL2-1", "cLevel2-1val");
    cParamsLevel2.put("cL2-2", "cLevel2-2val");
    cParamsLevel1.put("cL1-3", cParamsLevel2);

    params.put("c", cParamsLevel1);

    System.out.println(httpBuildQuery(params, "UTF-8"));
}


private static void testWithList() {
    Map<String, Object> params = new LinkedHashMap<String, Object>();
    params.put("a", "1");
    params.put("b", "2");

    List<Object> cParams = new ArrayList<Object>();
    cParams.add("c1val");
    cParams.add("c2val");
    params.put("c", cParams);

    System.out.println(httpBuildQuery(params, "UTF-8"));
}


private static void testWithNestedList() {
    Map<String, Object> params = new LinkedHashMap<String, Object>();
    params.put("a", "1");
    params.put("b", "2");

    List<Object> cParamsLevel1 = new ArrayList<Object>();
    cParamsLevel1.add("cL1-val1");
    cParamsLevel1.add("cL12-val2");

    List<Object> cParamsLevel2 = new ArrayList<Object>();
    cParamsLevel2.add("cL2-val1");
    cParamsLevel2.add("cL2-val2");
    cParamsLevel1.add(cParamsLevel2);

    params.put("c", cParamsLevel1);

    System.out.println(httpBuildQuery(params, "UTF-8"));
}


private static void testCompound() {

    Map<String, Object> params = new LinkedHashMap<String, Object>();

    //flat
    params.put("a", "1");
    params.put("b", "2");

    //Map level 1
    Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
    cParamsLevel1.put("cL1-1", "cLevel1-1val");
    cParamsLevel1.put("cL1-2", "cLevel1-2val");

    //Map level 2
    Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
    cParamsLevel2.put("cL2-1", "cLevel2-1val");
    cParamsLevel2.put("cL2-2", "cLevel2-2val");
    cParamsLevel1.put("cL1-3", cParamsLevel2);

    params.put("c", cParamsLevel1);

    //List level 1
    List<Object> dParamsLevel1 = new ArrayList<Object>();
    dParamsLevel1.add("dL1-val1");
    dParamsLevel1.add("dL12-val2");

    //List level 2
    List<Object> dParamsLevel2 = new ArrayList<Object>();
    dParamsLevel2.add("dL2-val1");
    dParamsLevel2.add("dL2-val2");
    dParamsLevel1.add(dParamsLevel2);

    params.put("d", dParamsLevel1);

    System.out.println(httpBuildQuery(params, "UTF-8"));

}

}

For easy test of your results append the string resulted by tests as query String of real url that point to this PHP. Example

http://localhost/test.php?a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val&d[0]=dL1-val1&d[1]=dL12-val2&d[2][0]=dL2-val1&d[2][1]=dL2-val2
<?php
var_dump($_REQUEST);
?>
like image 38
Gilad Avatar answered Oct 18 '22 21:10

Gilad


This should be the easiest (and most reliable) solution:

protected static String httpBuildQuery(List<? extends NameValuePair> parameters, String encoding) {
    return URLEncodedUtils.format(parameters, encoding).replace("*", "%2A");
}

Example usage:

List<NameValuePair> params = new ArrayList<NameValuePair>;
params.add(new BasicNameValuePair("key", "value"));

String queryString = httpBuildQuery(myParamList, "UTF-8");

Java not encoding the asterisk (+) while PHP does encode it %2A should be the only difference.

like image 23
caw Avatar answered Oct 18 '22 22:10

caw