Theory:Handling requests with bodies
When we want to pass information to a web application server, we usually opt for POST
methods. We can actually send information of any type, even an unformatted raw string. But we tend to work with JSON, as it is one of the easiest formats to work with. JSON data can be easily converted to objects with Spring, so we can work with more complex data.
We will use an annotation called @RequestBody
to accept JSON data via @RestController
. This annotation can send data of a specific format, including JSON, in a request's body.
We will use the basic project. If you don't have this application, visit the Spring Initializr (opens new window) site and generate it with Gradle and Java.
# Sending an object to the server
The @RequestBody
annotation is used in @RestController
to send data to a path through the body of the request. A request body can be used to send data in a variety of formats. By default, Spring expects data in JSON format, so we will start by looking at how JSON data can be sent using a @RequestBody
annotation.
First, we will create an object to represent the JSON data that will be sent to the application. In this example, we will create an application that works with user data, including the name, id, phone number, and status of the user's account. Our object can be set up as shown below:
public class UserInfo {
private int id;
private String name;
private String phone;
private boolean enabled;
// getters and setters
UserInfo() {}
}
2
3
4
5
6
7
8
9
10
11
Now, let's create a simple POST
request that accepts a JSON representation of the UserInfo
object. The POST
request will return the user's account name and the status of the account:
@RestController
public class UserInfoController {
@PostMapping("/user")
public String userStatus(@RequestBody UserInfo user) {
if (user.isEnabled()) {
return String.format("Hello! %s. Your account is enabled.", user.getName());
} else {
return String.format(
"Hello! Nice to see you, %s! Your account is disabled",
user.getName()
);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
When we generate our POST
request to the /user
path, we need to provide a query body that defines a valid UserInfo
object. This data is provided so that each object property is defined as an entry to the JSON object. This means that the request should contain an id, name, phone, and status:
When adding a body in Postman, you can choose the JSON format by setting the raw option and navigating to JSON in the dropdown menu. It sends the provided JSON data in the request body to the user
object in our code. Spring can construct a UserInfo
object with JSON properties and initialize it with getters and setters implemented in the code.
We can send more complex data to our application with @RequestBody
. There are a few other formats we can utilize in the@RequestBody
annotation. We will explore them in the next section.
# Sending multiple objects
It is possible to send multiple JSON objects in a single request using a list of objects in our @RequestBody
.To implement a list-based @RequestBody
, we need to change the type from a single object to a list of objects:
@RestController
public class UserInfoController {
@PostMapping("/user")
public String userStatus(@RequestBody List<UserInfo> userList) {
return String.format("Added %d users", userList.size());
}
}
2
3
4
5
6
7
8
In this example, our @RequestBody
now accepts a list of UserInfo
type. So the JSON we send to the server should now be a list of JSON objects. Use rectangular brackets []
to create a list of JSON objects. A list contains a sequence of one or more JSON objects, as shown below:
After the request has been sent, the JSON array can be iterated, and each object is placed in the UserInfo
list. In our example above, we output the number of objects that have been passed through the request.
# Additional data formats
In addition to JSON arrays, it is also possible to use a different format. For example, we can use XML to pass objects through our @RequestBody
annotation. To do this, we need to add consumes = MediaType.APPLICATION_XML_VALUE
to the @PostMapping
annotation:
@RestController
public class UserInfoController {
@PostMapping(value = "/user", consumes = MediaType.APPLICATION_XML_VALUE)
public String userStatus(@RequestBody UserInfo user) {
return String.format("Added User %s", user);
}
}
2
3
4
5
6
7
8
Using the consumes
argument, it is possible to customize the data that is sent to the POST
request. When the consumes
argument is added to the mapping, we also need to label the path argument with value
. This allows Spring to distinguish between the arguments. If a consumes
argument is not provided, it will be JSON by default. There are many other MediaType
values. For example, TEXT_PLAIN
can be used for plain text, and TEXT_HTML
can be used for HTML formats.
提示
A full list of available formats can be found in the official documentation (opens new window).
# Conclusion
In this topic, we have discussed a few ways to make @RestController
handle requests with bodies:
- Add a
@RequestBody
annotation to the parameter of the mapping; - Create a class to map a body to an object with getters and setters;
- If we want to include a consumable that isn't JSON, add the consumes argument to mapping.
After these steps, your method will be able to read a passed request body in any required format.