0

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.

4
  • Is it always the same parameter or can that be in the value of any parameter? Commented Apr 8, 2021 at 7:06
  • Can be any parameter. And also there can be many similar parameters or other symbols too in value Commented Apr 8, 2021 at 7:09
  • You should fix the caller to your method. You are starting with invalid input - how are you ever going to determine reliably which & in any input string is the one to fix? Commented Apr 8, 2021 at 10:54
  • @DuncG I have mentioned in question that I don't have access to caller. I am getting the complete url in string format and need to deal with that. Commented Apr 8, 2021 at 13:25

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

As I have mentioned in question, the function directly gets url in string format, I don't have access to how its being passed. So, need a solution that directly works on string. I cannot get requestParams saperatly.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.