Spring restful webservice returning JSON - java

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)));
}

Related

How to access Spring controller's JSON parameter?

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.

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;
}

returning multiple different objects in #RestController method

I am currently working with Spring Rest Web Services and I have set up a #RestController with some methods that each have a #RequestMapping. The problem is that each method can of course only return objects of one type. However, for each request, I might want to return an instance of Class A, one property of Class B and a List containing objects of Class C. Of course, I could make multiple requests, but is there a way we can return multiple different objects with one request?
For further information: I would like to send the objects back to a mobile client in XML format.
You can make your method to return Map<String,Object>:
#RequestMapping(value = "testMap", method = RequestMethod.GET)
public Map<String,Object> getTestMap() {
Map<String,Object> map=new HashMap<>();
//put all the values in the map
return map;
}
You can return a JsonNode
#RequestMapping(..)
#ResponseBody
public JsonNode myGetRequest(){
...
//rawJsonString is the raw Json that we want to proxy back to the client
return objectMapper.readTree(rawJsonString);
}
The Jackson converter know how to transform the JsonNode into plain Json.
Or you can tell Spring that your method produces json produces="application/json"
#RequestMapping(value = "test", method = RequestMethod.GET, produces="application/json")
public #ResponseBody
String getTest() {
return "{\"a\":1, \"b\":\"foo\"}";
}

ResponseBody in Spring MVC 2

I am currently working on implementing REST webservices into existing system. This system is using Spring in version 2 (particularly 2.5.6.SEC02). I can't upgrade it to version 3 as it could break existing system components. We didn't make the rest of this system, don't have source codes and don't want to lose warranty, so Spring version should basically stay as it is :)
The question is, how can I implement Rest WS with automatic DTO serialization from/to JSON? I have appropriate Jackson libraries on the classpath. Spring 2 doesn't seem to know about #RequestBody and #ResponseBody yet. Are there any other annotations that can be used, or some alternative way?
You may need to manually parse the JSON String and write it to the response for this to work for you. I suggest using the jackson2 API.
https://github.com/FasterXML/jackson
First, accept a json String as the argument from the request, and then manually parse the String to and from a POJO using the jackson ObjectMapper.
Here's the jQuery/JavaScript:
function incrementAge(){
var person = {name:"Hubert",age:32};
$.ajax({
dataType: "json",
url: "/myapp/MyAction",
type: "POST",
data: {
person: JSON.stringify(person)
}
})
.done(function (response, textStatus, jqXHR) {
alert(response.name);//Hubert
alert(response.age);//33
//Do stuff here
});
}
The person pojo:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
//Allows name or age to be null or empty, which I like to do to make things easier on the JavaScript side
#JsonIgnoreProperties(ignoreUnknown = true)
public class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
And here's the the controller:
import com.fasterxml.jackson.databind.ObjectMapper;
/*snip*/
#Controller
public class MyController{
//I prefer to have a single instance of the mapper and then inject it using Spring autowiring
private ObjectMapper mapper;
#Autowired
public MyController(ObjectMapper objectMapper){
this.objectMapper = objectMapper;
}
#RequestMapping(value="/myapp/MyAction", method= {RequestMethod.POST})
public void myAction(#RequestParam(value = "person") String json,
HttpServletResponse response) throws IOException {
Person pojo = objectMapper.readValue(new StringReader(json), Person.class);
int age = pojo.getAge();
age++;
pojo.setAge(age);
objectMapper.writeValue(response.getOutputStream(),pojo);
}
}
You can try a DIY approach with Spring MVC controllers and JSONObject from json.org. Just use it to json-serialize your returned objects and flush it down the response, with the appropiate headers.
It has its pitfalls (I would recommend you use a simple wrapper class with a getter when you try to send a collection), but I have been happy with it for some years.

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"]
}

Categories