I will like to use the JSON response inside a controller. I am calling a method that returns the JSON. See my code below. Please how do I loop through the Json object returned inside my controller. I need to use the properties like sending mail to the email addresses from another method inside my controller .
My method that does that returns the JSON :
#ResponseBody
private ResponseEntity<?> queryIsw(String ref, String amt) throws Exception{
String pdtid = "62";
String salt = "D3D1D05AFE42AD50818167EAC73C109168A0F108";
RestTemplate restt = new RestTemplate();
String uri = "https://bestng.com/gettransaction.json";
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("productid", pdtid);
params.add("transactionreference", ref);
params.add("amount", amt);
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(uri).queryParams(params).build();
URI oro = uriComponents.toUri();
HttpHeaders hea = new HttpHeaders();
String hs = pasher(pdtid, ref, salt);
hea.add("hash", hs);
HttpEntity<String> hent = new HttpEntity<String>(hea);
ResponseEntity<Object> resp = restt.exchange(oro, HttpMethod.GET, hent, Object.class);
return resp;
}
Below is my call to this method above from another method :
ResponseEntity<?> dres = queryIsw(dref,ama);
Kindly explain how I can use properties of 'dres' returned in my controller .
Thanks
Try taking a look at the Jackson JSON to Java mapping tools and specifically the ObjectMapper. It can convert a properly formatted JSON string into an object hierarchy from which you can pull out the data that you need. Jackson is a frequently used tool for this activity. Take a look at the tutorial for more details:
http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
If you need more help, do ask.
I am assuming that it will return within the body of the ResponseEntity.
Try:
String body = dres.getBody();
You can use something that can parse that string to a json object. Something like:
JSONObject jObject = new JSONObject(body);
See:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html
Java String to JSON conversion
Related
I am working on a Spring Boot project performing REST call to an external API in this way:
#Override
public List<NotaryDistrictDetails> getNotaryDistrictDetailsByDistictId(String districtId) throws URISyntaxException {
String completeURL = this.wpPortalBasicNotaryDistrictPostBaseURL.replace("{districtId}", districtId);
System.out.println("completeURL: " + completeURL);
URI uri = new URI(completeURL);
System.out.println(uri);
ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
System.out.println(forEntity.getStatusCodeValue());
System.out.println(forEntity.getBody());
return null;
}
At the moment the println output is something like this (and this is correct):
200
[{"post_type":"notary-district","ID":38804,"wpcf-idnotary-district":"XXX","post_title":"AA"}]
I know that to retrieve a specific field I can create a model object containing these fields and then do something like:
ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, MyModelClass.class);
and then retrieve all my properties.
but in this case I have only to retrieve the value of a single specific field from the previous JSON repsonse, the ID field, this one "ID":38804. This because I have rto use this retrieved value to perform a second external API call passing this ID as paramether.
My question is: exist a way to directly retrieve a single field value (in this case the ID field value) avoiding to create a model class for this response? Or have I to create a model class and retrieve the whole object related to my response and from here retrieve the ID field?
As suggested in the comment of my original post I solved using JsonNode Jackson object, following my solution:
#Override
public List<NotaryDistrictDetails> getNotaryDistrictDetailsByDistictId(String districtId) throws URISyntaxException, JsonMappingException, JsonProcessingException {
String completeURL = this.wpPortalBasicNotaryDistrictPostBaseURL.replace("{districtId}", districtId);
System.out.println("completeURL: " + completeURL);
URI uri = new URI(completeURL);
System.out.println(uri);
ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(forEntity.getBody());
System.out.println("jsonNode: " + jsonNode.get(0).toPrettyString());
System.out.println("ID: " + jsonNode.get(0).get("ID"));
return null;
}
Try this one
ParameterizedTypeReference<Map<String, Object>> responseType =
new ParameterizedTypeReference<Map<String, Object>>() {};
ResponseEntity<Map<String, Object>> responseEntity =
restTemplate.exchange(uri, HttpMethod.GET, entity, responseType);
Then get the required value by key
I have this method to make request:
#Override
public HttpEntity<MultiValueMap<String, String>> generateRequestEntity(Date date) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("key", "SOME_API_KEY");
map.add("source", "SOME_API_SOURCE");
if (date == null)
map.add("method", "getall");
else {
map.add("method", "getfrom");
map.add("date", new SimpleDateFormat("yyyy-MM-dd").format(date));
}
return new HttpEntity<>(map, headers);
}
I send a request and get a response, as recommended at following link: URL
HttpEntity<MultiValueMap<String, String>> request = generateRequestEntity(date);
ResponseEntity<OnlineSell[]> response = restTemplate.postForEntity(url, request, OnlineSell[].class);
OnlineSell[] onlineSells = response.getBody();
But I have a problem. I am failing when trying to parse JSON-response. OnlineSell - class, that must keep the answer BUT I just can’t create a structure that successfully stores the values of this answer. A very large and complex answer tree comes.
Answer: Can I get JSONObject from it to parse and save manually? Or can I get help with JSON parsing by previously updating this post and adding it (answer form Postman)?
What you can do is to consider the ResponseEntity as a String.
Then afterwards you can use objectMapper with readValue(),
Something like this:
ResponseEntity<String> response = restTemplate().postForEntity(url, request, String.class);
String body = response.getBody();
OnlineSell[] onlineSells = new ObjectMapper().readValue(body, OnlineSell[].class);
I am new to web programming in general, especially in Java, so I just learned what a header and body is.
I'm writing RESTful services using Spring MVC. I am able to create simple services with the #RequestMapping in my controllers. I need help understanding how to get HTTP header information from a request that comes to my method in my REST service controller. I would like to parse out the header and get some attributes from it.
Could you explain how I go about getting that information?
When you annotate a parameter with #RequestHeader, the parameter retrieves the header information. So you can just do something like this:
#RequestHeader("Accept")
to get the Accept header.
So from the documentation:
#RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(#RequestHeader("Accept-Encoding") String encoding,
#RequestHeader("Keep-Alive") long keepAlive) {
}
The Accept-Encoding and Keep-Alive header values are provided in the encoding and keepAlive parameters respectively.
And no worries. We are all noobs with something.
You can use the #RequestHeader annotation with HttpHeaders method parameter to gain access to all request headers:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers) {
// Use headers to get the information about all the request headers
long contentLength = headers.getContentLength();
// ...
StreamSource source = new StreamSource(new StringReader(body));
YourObject obj = (YourObject) jaxb2Mashaller.unmarshal(source);
// ...
}
My solution in Header parameters with example is user="test" is:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers){
System.out.println(headers.get("user"));
}
You can use HttpEntity to read both Body and Headers.
#RequestMapping(value = "/restURL")
public String serveRest(HttpEntity<String> httpEntity){
MultiValueMap<String, String> headers =
httpEntity.getHeaders();
Iterator<Map.Entry<String, List<String>>> s =
headers.entrySet().iterator();
while(s.hasNext()) {
Map.Entry<String, List<String>> obj = s.next();
String key = obj.getKey();
List<String> value = obj.getValue();
}
String body = httpEntity.getBody();
}
I have a POJO of the form:
#Data
public class BaseRequest {
private String type;
private Map<String, Object> details;
private Map<String, Object> signature;
}
I have a service running which only accepts Content Type: "application/x-www-form-urlencoded".
I have written a client in Java which uses Spring's RestTemplate to make calls.
public String getInvoice(BaseRequest req, String url) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req, headers);
String response = this.restTemplate.postForObject(url, httpEntity, String.class);
return response;
}
However, it throws an error:
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.x.y.z.BaseRequest] and content type [application/x-www-form-urlencoded]
It works if I set the content type as JSON:
headers.setContentType(MediaType.APPLICATION_JSON);
I know it works for JSON because I have configured my RestTemplate Bean with JacksonHTTPMessageConverter. So I can easily convert POJOs to application/json. However, I am not able to figure out how to do that with application/x-www-form-urlencoded.
I've been searching this for awhile now, and the only solution which I've found is to write my own converter to convert my BaseRequest class to Spring's MultiValueMap, and then Spring's FormHttpMessageConverter will automatically handle it. But I want to avoid doing that. Is there any other way around this?
Any leads would be appreciated. Thanks!
EDIT:
My question is different from #JsonProperty not working for Content-Type : application/x-www-form-urlencoded. The conversion happening there is about accepting data in application/x-www-form-urlencoded and converting it to a POJO. My question is about converting a POJO to application/x-www-form-urlencoded while using Spring's resttemplate to make calls. And like I mentioned, I know I can achieve this by writing my own converter to convert my POJO to Spring's MultiValueMap. However, I want to know if I can avoid doing this.
EDIT:
Dump of $_POST on the API when I send my data as MultiValueMap<String, Object>:
"array(0) {
}"
Dump of $_POST on the API when I send my data through Postman in the correct format:
"array(2) {
["type"]=>
string(16) "abcd"
["details"]=>
array(1) {
["template_file"]=>
string(16) "x.html"
}
}"
Try to convert your nested object in request payload to the org.springframework.util.MultiValueMap. Add and implement converter method in your POJO
public class BaseRequest {
// ...
public MultiValueMap<String, Object> toMap() {
MultiValueMap<String, Object> result = new LinkedMultiValueMap<>();
result.add("type", type);
result.put("details", details);
result.put("signature", signature);
return result;
}
}
Now use it during request creation
HttpEntity<BaseRequest> httpEntity = new HttpEntity<BaseRequest>(req.toMap(), headers);
That is caused because inside FormHttpMessageConverter which performs actual conversion method canRead(Class<?>, MediaType) checks if MultiValueMap.class.isAssignableFrom(clazz) where clazz is your payload object. In your case it failed, so FormHttpMessageConverter skipped.
Hope it helps!
I struggled with an extrange spring behavior using RestTemplate (org.springframework.web.client.RestTemplate) without success.
I use in my hole application below code and always receive an XML response, which I parse and evaluate its result.
String apiResponse = getRestTemplate().postForObject(url, body, String.class);
But can't figure out why a server response is in JSON format after executing:
String apiResponse = getRestTemplate().getForObject(url, String.class);
I've debugged at low level RestTemplate and the content type is XML, but have no idea why the result is in JSON.
When I access from a browser the response is also in XML, but in apiResponse I got JSON.
I tried many options after reading Spring documentation
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/web/client/RestTemplate.html
Also tried to modify explicitly the headers but still can't figure it out.
I debugged RestTemplate class and noticed that this method is always setting application/json:
public void doWithRequest(ClientHttpRequest request) throws IOException {
if (responseType != null) {
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter.canRead(responseType, null)) {
List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
for (MediaType supportedMediaType : supportedMediaTypes) {
if (supportedMediaType.getCharSet() != null) {
supportedMediaType =
new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
}
allSupportedMediaTypes.add(supportedMediaType);
}
}
}
if (!allSupportedMediaTypes.isEmpty()) {
MediaType.sortBySpecificity(allSupportedMediaTypes);
if (logger.isDebugEnabled()) {
logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
}
request.getHeaders().setAccept(allSupportedMediaTypes);
}
}
}
Could you give an idea?
I could solve my issue with RC.'s help. I'll post the answer to help other people.
The problem was that Accept header is automatically set to APPLICATION/JSON so I had to change the way to invoke the service in order to provide the Accept header I want.
I changed this:
String response = getRestTemplate().getForObject(url, String.class);
To this in order to make the application work:
// Set XML content type explicitly to force response in XML (If not spring gets response in JSON)
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = getRestTemplate().exchange(url, HttpMethod.GET, entity, String.class);
String responseBody = response.getBody();