Akshay Borse
Akshay Borse

Reputation: 45

Encode & in query parameter value in string url in java

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

Answers (2)

Akshay Borse
Akshay Borse

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

Massoud Azizi
Massoud Azizi

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

Related Questions