Encoding curly braces in Jersey Client 2

Instead of manually pre-encoding the query parameter value, a better way might be do always use a template parameter and then use resolveTemplate() with the un-safe value.

Client client = ClientBuilder.newClient();

WebTarget target = client.target("http://server")
            .path("/foo")
            .queryParam("bar", "{bar}")
            .resolveTemplate("bar", "{\"foo\":\"bar\"}");

assertThat(target.getUri().toString())
        .isEqualTo("http://server/foo?bar=%7B%22foo%22%3A%22bar%22%7D");

So, first of all it's insane that Jersey is doing templating by default. Secondly, all the solutions here are wrong...doing URLEncoder.encode(..., "UTF-8") will not work for query params which contains spaces. Since the URLEncoder will encode the space as +, which Jersey will interpret as a plus sign, so Jersey ends up encoding it as %2B. See https://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html for reference.

My proposed solution, which I'm not very happy with (as always with Java) is to replace all { and } with %7B and %7D respectively, as following:

Map<String, String> map = new HashMap<>();
map.put("paramWithCurly", " {with a space}".replaceAll("\\{", "%7B").replaceAll("\\}", "%7D"));
map.put("paramWithOutCurly", "with a space");
map.put("paramWithBracket", "[with a space]");
WebTarget target = client.target(url);
for (Map.Entry<String, String> entry : map.entrySet()) {
    target = target.queryParam(entry.getKey(), entry.getValue());
}