I'd like to append key-value pair as a query parameter to an existing URL. While I could do this by checking for the existence of whether the URL has a query part or a fragment part and doing the append by jumping though a bunch of if-clauses but I was wondering if there was clean way if doing this through the Apache Commons libraries or something equivalent.
http://example.com
would be http://example.com?name=John
http://example.com#fragment
would be http://example.com?name=John#fragment
http://[email protected]
would be http://[email protected]&name=John
http://[email protected]#fragment
would be http://[email protected]&name=John#fragment
I've run this scenario many times before and I'd like to do this without breaking the URL in any way.
I suggest an improvement of the Adam's answer accepting HashMap as parameter
/**
* Append parameters to given url
* @param url
* @param parameters
* @return new String url with given parameters
* @throws URISyntaxException
*/
public static String appendToUrl(String url, HashMap<String, String> parameters) throws URISyntaxException
{
URI uri = new URI(url);
String query = uri.getQuery();
StringBuilder builder = new StringBuilder();
if (query != null)
builder.append(query);
for (Map.Entry<String, String> entry: parameters.entrySet())
{
String keyValueParam = entry.getKey() + "=" + entry.getValue();
if (!builder.toString().isEmpty())
builder.append("&");
builder.append(keyValueParam);
}
URI newUri = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), builder.toString(), uri.getFragment());
return newUri.toString();
}
There are plenty of libraries that can help you with URI building (don't reinvent the wheel). Here are three to get you started:
import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();
import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();
import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();
See also: GIST > URI Builder Tests
Kotlin & clean, so you don't have to refactor before code review:
private fun addQueryParameters(url: String?): String? {
val uri = URI(url)
val queryParams = StringBuilder(uri.query.orEmpty())
if (queryParams.isNotEmpty())
queryParams.append('&')
queryParams.append(URLEncoder.encode("$QUERY_PARAM=$param", Xml.Encoding.UTF_8.name))
return URI(uri.scheme, uri.authority, uri.path, queryParams.toString(), uri.fragment).toString()
}
Use the URI
class.
Create a new URI
with your existing String
to "break it up" to parts, and instantiate another one to assemble the modified url:
URI u = new URI("http://[email protected]&name=John#fragment");
// Modify the query: append your new parameter
StringBuilder sb = new StringBuilder(u.getQuery() == null ? "" : u.getQuery());
if (sb.length() > 0)
sb.append('&');
sb.append(URLEncoder.encode("paramName", "UTF-8"));
sb.append('=');
sb.append(URLEncoder.encode("paramValue", "UTF-8"));
// Build the new url with the modified query:
URI u2 = new URI(u.getScheme(), u.getAuthority(), u.getPath(),
sb.toString(), u.getFragment());
For android, Use: https://developer.android.com/reference/android/net/Uri#buildUpon()
URI oldUri = new URI(uri);
Uri.Builder builder = oldUri.buildUpon();
builder.appendQueryParameter("newParameter", "dummyvalue");
Uri newUri = builder.build();
An update to Adam's answer considering tryp's answer too. Don't have to instantiate a String in the loop.
public static URI appendUri(String uri, Map<String, String> parameters) throws URISyntaxException {
URI oldUri = new URI(uri);
StringBuilder queries = new StringBuilder();
for(Map.Entry<String, String> query: parameters.entrySet()) {
queries.append( "&" + query.getKey()+"="+query.getValue());
}
String newQuery = oldUri.getQuery();
if (newQuery == null) {
newQuery = queries.substring(1);
} else {
newQuery += queries.toString();
}
URI newUri = new URI(oldUri.getScheme(), oldUri.getAuthority(),
oldUri.getPath(), newQuery, oldUri.getFragment());
return newUri;
}
Source: Stackoverflow.com