Java URL encoding of query string parameters
URLEncoder
is the way to go. You only need to keep in mind to encode only the individual query string parameter name and/or value, not the entire URL, for sure not the query string parameter separator character &
nor the parameter name-value separator character =
.
String q = "random word £500 bank $";
String url = "https://example.com?q=" + URLEncoder.encode(q, StandardCharsets.UTF_8);
When you're still not on Java 10 or newer, then use StandardCharsets.UTF_8.toString()
as charset argument, or when you're still not on Java 7 or newer, then use "UTF-8"
.
Note that spaces in query parameters are represented by +
, not %20
, which is legitimately valid. The %20
is usually to be used to represent spaces in URI itself (the part before the URI-query string separator character ?
), not in query string (the part after ?
).
Also note that there are three encode()
methods. One without Charset
as second argument and another with String
as second argument which throws a checked exception. The one without Charset
argument is deprecated. Never use it and always specify the Charset
argument. The javadoc even explicitly recommends to use the UTF-8 encoding, as mandated by RFC3986 and W3C.
All other characters are unsafe and are first converted into one or more bytes using some encoding scheme. Then each byte is represented by the 3-character string "%xy", where xy is the two-digit hexadecimal representation of the byte. The recommended encoding scheme to use is UTF-8. However, for compatibility reasons, if an encoding is not specified, then the default encoding of the platform is used.
See also:
- What every web developer must know about URL encoding
Encoding URL query parameters in Java
java.net.URLEncoder.encode(String s, String encoding)
can help too. It follows the HTML form encoding application/x-www-form-urlencoded
.
URLEncoder.encode(query, "UTF-8");
On the other hand, Percent-encoding (also known as URL encoding) encodes space with %20
. Colon is a reserved character, so :
will still remain a colon, after encoding.
Encode & in query parameter value in string url in java
Here is how I have solved my problem
private URI convertStringURLToURI(String url) {
URI uri = null;
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(url);
String queryParameter = uriComponentsBuilder.build().toUri().getQuery();
if(queryParameter != null) {
// Split the query part into queries
String[] splitedQueryParameter = queryParameter.split("&");
Stack<String> queryParamStack = new Stack<>();
for(int i = 0; i < splitedQueryParameter.length; i++) {
/*
In case "&" is present in any of the query values ex. b=abc & xyz then
it would have split as "b=abc" and "xyz" due to "&" symbol
Below code handle such situation
If "=" is present in any value then it is pushed to stack,
else "=" is not present then this value was part of the previous push query
due to "&" present in query value, so the else part handles this situation
*/
if(splitedQueryParameter[i].contains("=")) {
queryParamStack.push(splitedQueryParameter[i]);
} else {
String oldValue = queryParamStack.pop();
String newValue = oldValue + "&" + splitedQueryParameter[i];
queryParamStack.push(newValue);
}
}
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
while(!queryParamStack.isEmpty()) {
String[] query = queryParamStack.pop().split("=");
String queryParameterValue = query[1];
/*
If in the query value, "=" is present somewhere then the query value would have
split into more than two parts, so below for loop handles that situation
*/
for(int i = 2; i < query.length; i++) {
queryParameterValue = queryParameterValue + "=" + query[i];
}
// encoding the query value and adding to Map
queryParams.add(query[0], UriUtils.encode(queryParameterValue, "UTF-8"));
}
uriComponentsBuilder.replaceQueryParams(queryParams);
try {
uri = new URI(uriComponentsBuilder.build().toString());
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return uri;
}
So, this String URL
String url = "http://www.example.com/site?a=abc&b=qwe & asd&c=foo ?bar=2";
becomes
URI uri = "http://www.example.com/site?c=foo%20%3Fbar%3D2&b=qwe%20%26%20asd&a=abc"
Here, the sequence of query gets changed due to the use of Stack, it will not cause any issue in executing the uri, however you can handle that by modifying the code
Encoding a URL Query Parameter so it can have a '+'
Found what I believe to be a decent solution. It turns out that a large part of the problem is actually the "exchange" function, which takes a string for a URL, but then re-encodes that URL for reasons I cannot fathom. However, the exchange function can be sent a java.net.URI instead. In this case, it does not try to interpolate anything, as it is already a URI. I then use java.net.URLEncoder.encode() to encode the pieces. I still have no idea why this isn't standard in Spring, but this should work.
private String mapToQueryString(Map<String, String> query) {
List<String> entries = new LinkedList<String>();
for (Map.Entry<String, String> entry : query.entrySet()) {
try {
entries.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
} catch(Exception e) {
log.error("Unable to encode string for URL: " + entry.getKey() + " / " + entry.getValue(), e);
}
}
return String.join("&", entries);
}
/* Later in the code */
String endpoint = "https://baseurl.example.com/blah";
String finalUrl = query.isEmpty() ? endpoint : endpoint + "?" + mapToQueryString(query);
URI uri;
try {
uri = new URI(finalUrl);
} catch(URISyntaxException e) {
log.error("Bad URL // " + finalUrl, e);
return null;
}
}
/* ... */
HttpEntity<TheResponse> resp = myRestTemplate.exchange(uri, ...)
How to read query param value if special character (&) part of query param value
If the & character is part of the name or value in the query string then it has to be percent encoded. In the given example: contentName=abc%26def&path=Test&type=folder
.
Encoding query parameters in rest assured
You need to provide a second parameter to give the character-set to use for the encoding to take place:
String restUrl = URLEncoder.encode(queryParam, StandardCharsets.UTF_8);
Should work
https://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html Second method is listed below the deprecated one you're using.
Related Topics
Java Processbuilder: Resultant Process Hangs
Will System.Currenttimemillis Always Return a Value ≫= Previous Calls
Do Line Endings Differ Between Windows and Linux
Relation Between Memory Host and Memory Arguments Xms and Xmx from Java
Distinguishing Between Java Threads and Os Threads
Java Refuses to Start - Could Not Reserve Enough Space For Object Heap
Why Maven Uses Jdk 1.6 But My Java -Version Is 1.7
Eclipse/Tomcat: Deploy Doesn't Work Any More (Classnotfoundexception)
Rjava Load Error in Rstudio/R After "Upgrading" to Osx Yosemite
Selenium: How to Stop Geckodriver Process Impacting Pc Memory, Without Calling Driver.Quit()
Is Java "Pass-By-Reference" or "Pass-By-Value"
The Use of Multiple Jframes: Good or Bad Practice
How to Set Java_Home in Linux For All Users
Downloading Java Jdk on Linux Via Wget Is Shown License Page Instead