You don't even need ResponseEntitys! Just use getForObject with a String.class like:
final RestTemplate restTemplate = new RestTemplate();
final String response = restTemplate.getForObject("https://httpbin.org/ip", String.class);
System.out.println(response);
It will print something like:
{
"origin": "1.2.3.4"
}
Answer from madhead on Stack OverflowYou don't even need ResponseEntitys! Just use getForObject with a String.class like:
final RestTemplate restTemplate = new RestTemplate();
final String response = restTemplate.getForObject("https://httpbin.org/ip", String.class);
System.out.println(response);
It will print something like:
{
"origin": "1.2.3.4"
}
You can also use restTemplate.execute and pass ResponseExtractor that just parses the InputStream from the body.
public <T> T execute(String url,
org.springframework.http.HttpMethod method,
org.springframework.web.client.RequestCallback requestCallback,
org.springframework.web.client.ResponseExtractor<T> responseExtractor,
Object... uriVariables )
For example:
String rawJson = restTemplate.execute(url, HttpMethod.GET, (clientHttpRequest) -> {}, this::responseExtractor, uriVariables);
// response extractor would be something like this
private String responseExtractor(ClientHttpResponse response) throws IOException {
InputStream inputStream = response.getBody();
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
for (int length; (length = inputStream.read(buffer)) != -1; ) {
result.write(buffer, 0, length);
}
return result.toString("UTF-8");
}
This also bypasses ObjectMapper if your using Jackson and stringify invalid JSON.
Parse the JSON with a library (e.g. Jackson) and grab the token field.
String json = restTemplate.getForObject(url, String.class);
ObjectMapper mapper = new ObjectMapper();
return mapper.readTree(json).get("token").asText();
When you say String.class, you're asking RestTemplate to give you the result as a String. Instead, you can do either of these:
class TokenHolder {
String token;
}
TokenHolder holder = restTemplate.getForObject(url, TokenHolder.class);
holder.getToken();
or
// this is necessary because of generic type erasure
private static final ParameterizedTypeReference<Map<String, String>> MAP_TYPE =
new ParameterizedTypeReference<Map<String, String>>() {};
Map<String, String> map = restTemplate.getForObject(url, MAP);
map.get("token");
The "strong type" TokenHolder is generally preferable. Lombok's @Value and the brand-new Java Record feature can help create such classes with little boilerplate.
java - Get list of JSON objects with Spring RestTemplate - Stack Overflow
java - Receiving a JSON string response from a URL - Code Review Stack Exchange
java - GET request in RestTemplate in JSON - Stack Overflow
spring - RestTemplate and acessing json - Stack Overflow
I am using an api to retrieve some data which I did get but from that list of data I only want some stuffs I tried all the method yet nothing seems to work
this is the example JSON object
I am trying to only retrieve title and original tile
expect response is 200 but result is empty screen (in postman)
Thanks :)
---------------------------result from API in postman----------------------------------------
{
"page": 1,
"results": [
{
"backdrop_path": "/nxxCPRGTzxUH8SFMrIsvMmdxHti.jpg",
"id": 639720,
"original_title": "IF",
"overview": "A young girl who goes through a difficult experience begins to see everyone's imaginary friends who have been left behind as their real-life friends have grown up.",
"poster_path": "/xbKFv4KF3sVYuWKllLlwWDmuZP7.jpg",
"media_type": "movie",
"adult": false,
"title": "IF",
"original_language": "en",
"genre_ids": [
35,
14,
10751
],
"popularity": 937.037,
"release_date": "2024-05-08",
"video": false,
"vote_average": 7.477,
"vote_count": 244
},
----------------------------------------MY spring boot code below----------------------------
u/Slf4j
u/Service
public class MovieServices {
u/Setter
u/Getter
u/JsonIgnoreProperties(ignoreUnknown = true)
static class CollectionofMovies{
public List<MyMovies> result;
}
u/Getter
u/Setter
u/JsonIgnoreProperties(ignoreUnknown = true)
static class MyMovies{
u/JsonProperty("original_title")
public String originalTitle;
u/JsonProperty("title")
public String title;
}
private static final String url="https://api.themoviedb.org/3/trending/all/day?language=en-US";
private static final String key="Bearer --ooo"
u/Autowired
private RestTemplate restTemplate;
public List<MyMovies> allmovies() {
try {
HttpHeaders headers = new HttpHeaders();
headers.set("accept", "application/json");
headers.set("Authorization",key);
ResponseEntity<CollectionofMovies> response=restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), new ParameterizedTypeReference<CollectionofMovies>() {
});
if(response.getBody()!=null){
return response.getBody().getResult();
}
else {
throw new IllegalStateException("Response body is null");
}
}
catch (Exception e){
log.error("Something went wrong");
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR,"Error while fetching api ",e);
}
}
}First define an object to hold the entity coming back in the array.. e.g.
@JsonIgnoreProperties(ignoreUnknown = true)
public class Rate {
private String name;
private String code;
private Double rate;
// add getters and setters
}
Then you can consume the service and get a strongly typed list via:
ResponseEntity<List<Rate>> rateResponse =
restTemplate.exchange("https://bitpay.com/api/rates",
HttpMethod.GET, null, new ParameterizedTypeReference<List<Rate>>() {
});
List<Rate> rates = rateResponse.getBody();
The other solutions above will also work, but I like getting a strongly typed list back instead of an Object[].
Maybe this way...
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(urlGETList, Object[].class);
Object[] objects = responseEntity.getBody();
MediaType contentType = responseEntity.getHeaders().getContentType();
HttpStatus statusCode = responseEntity.getStatusCode();
Controller code for the RequestMapping
@RequestMapping(value="/Object/getList/", method=RequestMethod.GET)
public @ResponseBody List<Object> findAllObjects() {
List<Object> objects = new ArrayList<Object>();
return objects;
}
ResponseEntity is an extension of HttpEntity that adds a HttpStatus status code. Used in RestTemplate as well @Controller methods.
In RestTemplate this class is returned by getForEntity() and exchange().
OK, eventually, one of my co-workers helped me figure out why, believe it or not, it's this simple:
The endpoint was like this:
"http:localhost:8080/api/v1/items?itemIds=" + URLEncoder.encode(itemIds, "UTF-8");
However, it should be "http:localhost:8080/api/v1/items?itemIds=" + itemIds;
itemIds is just a comma-separated list.
After URLEncoder encoding via "UTF-8" schema, this comma-separated list becomes itemIds=5400028914%2C5400029138%2C5400029138%2C5400029138%2C5400029138%2C5400028401%2C5400028918%2C5400028076
from
itemIds=5400028914,5400029138,5400029138,5400029138,5400029138,5400028401,5400028918,5400028076,5400028726
We don't need to URLEncoder to encode the URL when using RestTemplate, anyone could help me deepen my understanding here please?
Thanks!
You don't need set "requestEntity" for a GET method, try your code like this:
public ItemInfo getItemInfo() throws Exception {
String url =
"http://localhost:8080/api/v1/items?itemIds=abc";
ObjectMapper objectMapper = new ObjectMapper();
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
String responseBody = response.getBody();
handlerError(response, url);
try {
return objectMapper.readValue(responseBody, ItemInfo.class);
} catch (IOException exception) {
LOGGER.error("failed to send REST request", exception);
throw new Exception(ErrorCode.NOT_AVAILABLE, url);
}
}
private void handlerError(final ResponseEntity<String> response, final String url) throws Exception {
String responseBody = response.getBody();
try {
if (RestUtil.isError(response.getStatusCode())) {
ObjectMapper objectMapper = new ObjectMapper();
MyInfoError myInfoError = objectMapper.readValue(responseBody, MyInfoError.class);
throw new Exception(infoErreur, ErrorCode.UNKNOWN_CODE_ERROR);
} else if (RestUtil.isNotFound(response.getStatusCode())) {
throw new Exception(ErrorCode.NOT_AVAILABLE, "MyService");
}
} catch (IOException exception) {
LOGGER.error("failed to send REST request", exception);
throw new Exception(ErrorCode.NOT_AVAILABLE, url);
}
}
I put it NULL because GET method not send any JSON request body/headers:
restTemplate.exchange(url, HttpMethod.GET, null, String.class);
OR: put your headers in GET method like this:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<?> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
For Example for POST you need to set requestEntity like below:
ItemFormRequest request =
new ItemFormRequest(1,"item no", "item name");
HttpEntity<ItemFormRequest> requestEntity = new HttpEntity<>(request);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
String responseBody = response.getBody();
Hope this help :)
The postForLocation method returns the value for the Location header. You should use postForObject with the String class, which returns the server's response.
So like this:
String result = restTemplate.postForObject(API_URL + "account/authenticate/?email={email}&token={token}", String.class, args);
This will return the response as a string.
Thanks to one of answers i've figured out how get the response from a POST with Spring by using the postForObject
String result = restTemplate.postForObject(API_URL + "account/authenticate/?email="+ AUTH_USER +"&token="+ AUTH_PASS, null, String.class);
For some reason i can't use arguments with MAP and have to put them inline in URL. But that's fine for me.
As of the "main key is result":
a. I would create a wrapper class for the actual payload if you deal with just one of this kind of web service:
public class Return{ // Class property cannot be called "return" because it is Java reserved name. @JsonProperty("return") private User[] array; .... getter and setter }b. If you deal with multiple webservices where actual payload is in "return" field I would create a generic wrapper class :
public class Return<T>{ // Class property cannot be called "return" because it is Java reserved name. @JsonProperty("return") private T[] array; .... getter and setter }Call to
RestRemplate:ResponseEntity<Return<User>> response = restTemplate.exchange(URL_GET, HttpMethod.GET, request, new ParameterizedTypeReference<Return<User>>(){}); User[] usersArray = response2.getBody().getArray();As of the property value in JSON attribute called "value" I would create two custom
JsonDeserializer(s): one for single value and one for array of values and annotate each property with@JsonDeserializewhere it applies:Single value deserializer:
public class StringValueDeserializer extends JsonDeserializer<String>{ @Override public String deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectCodec codec = parser.getCodec(); TreeNode node = codec.readTree(parser); JsonNode value = (JsonNode)node.get("value"); if (value != null){ return value.asText(); } return null; } }Array of values derializer:
public class StringArrayValueDeserializer extends JsonDeserializer<List<String>>{ @Override public List<String> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { List<String> ret = new ArrayList<>(); ObjectCodec codec = parser.getCodec(); TreeNode node = codec.readTree(parser); if (node.isArray()){ for (JsonNode n : (ArrayNode)node){ JsonNode value = n.get("value"); if (value != null){ ret.add(value.asText()); } } } return ret; } }Here you are new
User.class:public class User { private boolean admin; private String alias; private String email; @JsonDeserialize(using = StringValueDeserializer.class) private String emailId; @JsonDeserialize(using = StringArrayValueDeserializer.class) private ArrayList<String> groups; @JsonDeserialize(using = StringValueDeserializer.class) private String id; private boolean locked; private int loggedInCount; private boolean master; private String sms; @JsonDeserialize(using = StringValueDeserializer.class) private String smsId; private String type; private String username; .... getter and setter }
Good luck!
You can also use the JsonPath library to navigate through json:
String json = restTemplate.exchange(URL_GET,HttpMethod.GET,request, String.class);
DocumentContext document = JsonPath.parse(content, json);
List<User> users = document.read("$.return.*", new TypeRef<List<User>>() {});
This technique worked for me:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);
I ran across this problem when attempting to debug a REST endpoint. Here is a basic example using Spring's RestTemplate class to make a POST request that I used. It took me quite a bit of a long time to piece together code from different places to get a working version.
RestTemplate restTemplate = new RestTemplate();
String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);
The particular JSON parser my rest endpoint was using needed double quotes around field names so that's why I've escaped the double quotes in my requestJson String.