How to access Spring controller's JSON parameter? - java

I have a Spring controller which maps me JSON to some DTO object via message converter:
#RequestMapping(value = {"bar"},
consumes = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
public void foo(#RequestBody paramsDTO httpParams) {
// some logic here
}
Let's imagine, my DTO looks like:
public class paramsDTO {
String name;
String surName;
}
Is it possible to get access to name or surName values via some Servlet or Spring context (not directly from field)? I'm looking for something similar to HttpServletRequest#getParameterValues() but for the Spring JSON converter.

Related

Spring boot rest controller not converting request body to custom object

I have spring boot application which used spring rest controller .
This is the controller , below is the response an getting. Am using postman tool for sending request to this controller. And am sending content type as application/json
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody WebApp webapp, #RequestBody String propertyFiles, #RequestBody String) {
System.out.println("webapp :"+webapp);
System.out.println("propertyFiles :"+propertyFiles);
System.out.println("propertyText :"+propertyText);
return "ok good";
}
2018-03-21 12:18:47.732  WARN 8520 --- [nio-8099-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed
This is my postman request
{
"webapp":{"webappName":"cavion17","path":"ud1","isQA":true},
"propertyFiles":"vchannel",
"propertytText":"demo property"}
I tried by removing the RequestBody annotation, then able to hit the service , but param objects are received as null.
So please suggest how to retrieve objects in the restcontroller?
You cannot use multiple #RequestBody annotations in Spring. You need to wrap all these in an object.
Some like this
// some imports here
public class IncomingRequestBody {
private Webapp webapp;
private String propertryFiles;
private String propertyText;
// add getters and setters here
}
And in your controller
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody IncomingRequestBody requestBody) {
System.out.println(requestBody.getPropertyFiles());
// other statement
return "ok good";
}
Read more here
Passing multiple variables in #RequestBody to a Spring MVC controller using Ajax
Based on the sample postman payload you gave, you will need:
public class MyObject {
private MyWebapp webapp;
private String propertyFiles;
private String propertytText;
// your getters /setters here as needed
}
and
public class MyWebapp {
private String webappName;
private String path;
private boolean isQA;
// getters setters here
}
Then on your controller change it to:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(#RequestBody MyObject payload) {
// then access the fields from the payload like
payload.getPropertyFiles();
return "ok good";
}

Spring MVC Ignore Json property for a given controller method

I have a Java class (MyResponse) that is returned by a multiple RestController methods and has a lot of fields.
#RequestMapping(value = "offering", method=RequestMethod.POST)
public ResponseEntity<MyResponse> postOffering(...) {}
#RequestMapping(value = "someOtherMethod", method=RequestMethod.POST)
public ResponseEntity<MyResponse> someOtherMethod(...) {}
I want to ignore (e.g. not serialize it) one of the properties for just one method.
I don't want to ignore null fields for the class, because it may have a side effect on other fields.
#JsonInclude(Include.NON_NULL)
public class MyResponse { ... }
The JsonView looks good, but as far as I understand I have to annotate all other fields in the class with a #JsonView except the one that I want to ignore which sounds clumsy. If there is a way to do something like "reverse JsonView" it will be great.
Any ideas on how to ignore a property for a controller method?
Props to this guy.
By default (and in Spring Boot) MapperFeature.DEFAULT_VIEW_INCLUSION is enabled in Jackson. That means that all fields are included by default.
But if you annotate any field with a view that is different than the one on the controller method this field will be ignored.
public class View {
public interface Default{}
public interface Ignore{}
}
#JsonView(View.Default.class) //this method will ignore fields that are not annotated with View.Default
#RequestMapping(value = "offering", method=RequestMethod.POST)
public ResponseEntity<MyResponse> postOffering(...) {}
//this method will serialize all fields
#RequestMapping(value = "someOtherMethod", method=RequestMethod.POST)
public ResponseEntity<MyResponse> someOtherMethod(...) {}
public class MyResponse {
#JsonView(View.Ignore.class)
private String filed1;
private String field2;
}

How to bind set object to controller in spring

I am trying to make a post call to a controller, but the object I am expecting contains a Set datatype and I am unsure how the post data should look.
Models:
public class Notebook{
private string name;
private Set<Todo> todos;
}
public class Todo{
private String name;
}
Controller
#RequestMapping(method = RequestMethod.POST)
public void createNotebook(Notebook q){
questionnaireService.saveOrUpdateNotebook(q);
}
Currently I have tried posting like the example below:
curl --data "name=some notebook&todos[0].name=todo1&todos[1].name=todo2" http://localhost:8080/api/notebook
Doesn't seem to work. Anyone have experience with Sets?
You should qualify Notebook q with #RequestBody annotation so that the request can be mapped to an object of type Notebook. More about the format of the input data and the converters in Spring MVC doc: Mapping the request body with the #RequestBody annotation.
We send data from the front-end in JSON format and use Jackson JSON to convert it to the Java object. If you go that route, you can directly declare the todos as Set<String> and the input would be
{
name: "some notebook",
todos: ["todo1", "todo2"]
}

Spring restful webservice returning JSON

I just took the tutorial over at Spring.io http://spring.io/guides/gs/rest-service/ and created a simple rest service. But, does anybody know how I can return multiple objects in JSON format? If I for instance have a person class with a name and an id, how can I add three persons to /persons?
You can use the #ResponseBody annotation and just return whatever you want, providing that those objects can be jsonized.
For example, you can have a bean like this:
#Data
public class SomePojo {
private String someProp;
private List<String> someListOfProps;
}
and then in your controller you can have:
#ResponseBody
#RequestMapping("/someRequestMapping")
public List<SomePojo> getSomePojos(){
return Arrays.<String>asList(new SomePojo("someProp", Arrays.<String>asList("prop1", "prop2"));
}
and Spring by default would use its Jackson mapper to do it, so you'd get a response like:
[{"someProp":"someProp", "someListOfProps": ["prop1", "prop2"]}]
The same way, you can bind to some objects, but this time, using the #RequestBody annotation, where jackson would be used this time to pre-convert the json for you.
what you can do is
#RequestMapping("/someOtherRequestMapping")
public void doStuff(#RequestBody List<SomePojo> somePojos) {
//do stuff with the pojos
}
Try returning a list from the method:
#RequestMapping("/greetings")
public #ResponseBody List<Greeting> greetings(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return Arrays.asList(new Greeting(counter.incrementAndGet(),String.format(template, name)));
}

Proper way to allow json with and without root node using spring mvc and jackson

I have the following controller method:
#RequestMapping(value = "/v1/users/{userId}/settings", method = RequestMethod.POST, produces = { "application/json" }, consumes = { "application/json" })
#ResponseStatus(value = HttpStatus.CREATED)
#ResponseBody
public UserSetting createUserSetting(#PathVariable("userId") String userId,
#RequestBody Setting setting){
return userSettingService.createSetting(userId, userSetting);
}
When invoking the url /v1/users/12345/settings POST
with the payload
{"Setting":{"name":"CoolSetting", "id":"SETTING-ID"}}
the method behaves as expected.
What I would also like to accept is:
{"name":"CoolSetting", "id": "SETTING-ID"}
how do I accept the second payload version without the root tag.
The object in question looks like this
public class Setting{
#JsonProperty
private String id;
#JsonProperty
private String name;
//getters and setters removed
}
how can I tell spring to marshel using either json method?
You can use DeserializationConfig.Feature.UNWRAP_ROOT_VALUE property to achieve this result. For serialization use SerializationConfig.Feature.WRAP_ROOT_VALUE.
Detailed explanation and usage available in this blog: Jackson with and without root node

Categories