7

I am trying to achieve same thing as this: How to use query parameter represented as JSON with Spring RestTemplate?, sending JSON string as a URL parameter in restTemplate.exchange().

The accepted answer mentions that sending JSON object as request parameter is generally not a good idea since you will probably face problem with curly brackets inside JSON. That is exactly what is happening when I am trying to make a GET call to an API. Since this is an API from another system, I cannot ask them to change the format and will have to call the GET endpoint, passing JSON as parameter. How can I achieve this in restTemplate.exchange() call?

Note: The mentioned related question does not guide on how to overcome this problem and I do not have enough reputation to comment on it to ask the author of the answer.

5
  • And what's the problem with the response to the linked question? What is your code? What exact and complete error do you have? Commented Apr 6, 2017 at 10:41
  • The error I get is: java.lang.IllegalArgumentException: Not enough variable values available to expand '"size"'. The json looks like this: {"size":10000,"query":{"filtered":{"filter":{"term":{"run_id":"a5fc0cdb-0bce-4071-a850-77d181c0811d"}}}}} Commented Apr 6, 2017 at 10:46
  • The linked question only shows how to get JSON from an object, not how to use it in exchange() to avoid the error I mentioned above. Commented Apr 6, 2017 at 10:50
  • If you want help with your code, post your code. And yes, it does show how to build a URL with parameter values. Commented Apr 6, 2017 at 10:50
  • @JBNizet: I see.. I got it working by sending URI instead of String. Thanks! Commented Apr 6, 2017 at 12:46

3 Answers 3

17

Answering my own question. While it is a bad idea to pass JSON like this in a query/url parameter, there is a workaround as suggested here: https://jira.spring.io/browse/SPR-9220?focusedCommentId=76760&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-76760.
Replicating the code here in case this link goes dead:

String url = "http://localhost:8983/solr/select?wt=json&indent=true&fl=*&q=*:*&fq={!geofilt}&sfield=venue_location&pt=28.0674,-80.5595&d=25";
URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri();

System.out.println(uri);
// http://localhost:8983/solr/select?wt=json&indent=true&fl=*&q=*:*&fq=%7B!geofilt%7D&sfield=venue_location&pt=28.0674,-80.5595&d=25

Basically, instead of passing url having JSON query/url parameters as a string, pass it as a URI. Then call exchange method as before, but with URI instead of String:

restTemplate.exchange(uri, HttpMethod.GET, requestEntity, String.class)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your solution, passing an URI works like a charm! In my case, I need to pass some params: UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url); URI uri = builder.build().expand(params).encode().toUri(); restTemplate.getForObject(uri, String.class);
1

If this is 3rd party API and you cannot control or change JSON processing on backend side - there is no solution. Even if you will encode with URLEncoder - there is no guarantee that API backend would process such request correctly.

Comments

0

You can use URLEncoder class to encode the URL in exchange method, e.g.:

String url = "http://www.yoursite.com/api?param={\"some_key\":\"some_value\"}";
System.out.println(URLEncoder.encode(url, StandardCharsets.UTF_8.name()));

This will encode the characters (like braces and double quotes) and server then will decode it back to json.

6 Comments

I tried this. But exchange method ends up adding another encoding on top of this encoding, basically replacing all the % by %25. Hence, what server gets after decoding is another encoded string.
What if you send the request without encoding? Do you get 4xx or 5xx in return?
The error I get is: java.lang.IllegalArgumentException: Not enough variable values available to expand '"size"'. The json looks like this: {"size":10000,"query":{"filtered":{"filter":{"term":{"run_id":"a5fc0cdb-0bce-4071-a850-77d181c0811d"}}}}}
So, I assume it is coming back from server (possibly 500 error)? If yes, could you post the code for exchange method?
@ Darshan Mehta: No, the exception is thrown while building the URL, even before making the network call. I will add my code shortly.
|

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.