How to get raw JSON body in Spring REST controller? - java

The API below accept a json string from client, and the map it into a Email object. How can I get request body (email) as a raw String? (I want both raw-string and typed version of email parameter)
PS: This question is NOT a duplicate of: How to access plain json body in Spring rest controller?
#PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(#RequestBody Email email) {
//...
return new ResponseEntity<>(HttpStatus.OK);
}

You can do it in more than one way, listing two
1. **Taking string as the paramater**,
#PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(#RequestBody String email) {
//... the email is the string can be converted to Json using new JSONObject(email) or using jackson.
return new ResponseEntity<>(HttpStatus.OK);
}
2. **Using Jackson**
#PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(#RequestBody Email email) {
//...
ObjectMapper mapper = new ObjectMapper();
String email = mapper.writeValueAsString(email); //this is in string now
return new ResponseEntity<>(HttpStatus.OK);
}

Spring uses Jackson for this in the back, you could use it to serialize it to an string. Like so:
#Autowired private ObjectMapper jacksonMapper;
#PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(#RequestBody Email email) {
//...
log.info("Object as String: " + jacksonMapper.writeValueAsString(email));
return new ResponseEntity<>(HttpStatus.OK);
}

you can create json of type string using GSON library
Gson gson = new Gson();
#PostMapping(value = "/endpoint")
public ResponseEntity<Void> actionController(#RequestBody Car car) {
//...
log.info("Object as String: " + this.gson.toJson(car));
return new ResponseEntity<>(HttpStatus.OK);
}

I did not get all things about this question, but I try to answer as I understand. Well,
if you want to get request body:
as you say How to access plain json body in Spring rest controller? here already writen how to do this. If something wrong, maybe you send wrong json or not suitable type as you wite inside Email class. Maybe your request comes url filter
second way try like this:
private final ObjectMapper mapper = new ObjectMapper();
#PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(HttpServletRequest req) {
// read request body
InputStream body = req.getInputStream();
byte[] result = ByteStreams.toByteArray(body);
String text =new String(result,"UTF-8");
//convert to object
Email email = mapper.readValue(body, Email .class);
return new ResponseEntity<>(HttpStatus.OK);
}
If you want to convert object to json string read this post

Related

Using BodyInserters to pass parameter with webClient

There is my code.
public Mono<RespDto> function(TransReqDto1 reqDto1, TransReqDto2 reqDto2, String token) {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("TransReqDto1", reqDto1);
builder.part("TransReqDto2", reqDto2);
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
LinkedMultiValueMap map = new LinkedMultiValueMap();
map.add("TransReqDto1", reqDto1);
map.add("TransReqDto2", reqDto2);
return
client.post()
.uri("/api")
.body(BodyInserters.fromValue(reqDto1))
.headers(h -> h.setBearerAuth(token.split(" ")[1]))
.retrieve()
.bodyToMono(RespDto.class);
}
My probelm is that I need to send both reqDto1 & reqDto2. I've successfully sent reqDto1 with the code above but I can't figure out a way to send two objects.
Tried MultipartBodybuild and MultiValueMap but both are returning error from the target API. Please give me some hints!! Thank you
Here is the API I am trying to call!
#PostMapping("")
#ApiOperation(value = "test", notes = "test")
public Mono<?> transPost(#Valid #RequestBody TransReqDto1 reqDto1,
#Valid #RequestBody TransReqDto2 reqDto2) {
return testService.function(reqDto1, reqDto2);
}
You cannot use two #RequestBody. It can bind to a single object only. The expected way to do that is to create a wrapper DTO containing all the relevant data:
public class TransReqDto {
private TransReqDto1 transReqDto1;
private TransReqDto2 transReqDto2;
//...
}

Spring RestTemplate, can I retrieve a specific single field from the obtained JSON response avoiding to declare a model class?

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

ArrayObject in API Response along with status and message

I want the API Response to be as Follows:
{"success":"false/true","msg":"some message","data":{}}
if there is data the response data should print in "data":{}
ApiResponse Class
public ApiResponse(Boolean success, String message,JSONObject data) {
this.success = success;
this.message = message;
this.setData(data);
}
Data Returning in Controller
JSONObject dataObject = new JSONObject(user);
return new ResponseEntity(new ApiResponse(false, "User is Disabled",dataObject , HttpStatus.UNAUTHORIZED);
Spring boot would internally uses jackson objectmapper to serialize the object.
You can specify to include the fields even if they are null by using this property when you create the objectMapper bean
#Bean
ObjectMapper objectMapper() {
return Jackson2ObjectMapperBuilder.json()
.serializationInclusion(JsonInclude.Include.ALWAYS) // Include even empty values in the json
.build();
}

Send multiple key in Feign Client

I have a nxt request POST with form url encoded using Feign Client
#FeignClient(
url = "${url}", configuration = NxtApi.Configuration.class)
public interface NxtApi {
#PostMapping(value = "nxt", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
String new(
#RequestParam String requestType, #RequestBody Map<String, ?> payload);
class Configuration {
#Bean
Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
return new SpringFormEncoder(new SpringEncoder(converters));
}
#Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
}
I want to send the same key with two values
Map<String, Object> param = new HashMap<>();
param.put("filter", valueOne);
param.put("filter", valueTwo);
api.new("asset",param);
I need something like that
filter=valueOne&filter=valueTwo
But it's being sent like this (Request response in the log)
filter=[valueOne,valueTwo]
Thanks for any help.
You will have to use a List of String values instead of a Map.
#PostMapping(value = "nxt", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
String new(#RequestParam String requestType, #RequestParam("filter") List<String> filter, #RequestBody Map<String, ?> payload);
as I found it here: Spring Cloud Feign Client #RequestParam with List parameter creates a wrong request

How to loop through JSON response in Spring MVC Controller

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

Categories

Resources