Reputation: 45
I have function which get string url like this
String url = http://www.example.com/site?a=abc&b=qwe & asd
Here "qwe & asd" is a single query value
I want this url to get encoded into
URI url = http://www.example.com/site?a=abc&b=qwe%20%26%20asd"
I tried various methods but I am not able to encode & in "qwe & asd", the space is getting encoded to %20 but & is not getting encoded to %26.
The function gets url in string format only and complete url, I don't have access to how it is passed to function.
The symbol can be any symbol, in most cases it will be &, and there can be multiple parameters with similar value scenario.
Upvotes: 0
Views: 1667
Reputation: 45
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
Upvotes: 0
Reputation: 71
you can use URLEncoder for encoding your URL such as :
URLEncoder.encode(value, StandardCharsets.UTF_8.toString())
the result will be :
http://www.example.com/site?a=abc&b=qwe+%26+asd
URL encoding normally replaces a space with a plus (+) sign or with %20. you can use this code for encoding your url :
@SneakyThrows
private String encodeValue(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
}
@Test
void urlEncodingTest(){
Map<String, String> requestParams = new HashMap<>();
requestParams.put("a", "abc");
requestParams.put("b", "qwe & asd");
String encodedURL = requestParams.keySet().stream()
.map(key -> key + "=" + encodeValue(requestParams.get(key)))
.collect(joining("&", "http://www.example.com/site?", ""));
}
if you need more details you can check this link
Upvotes: 2