In previous video tutorials, I have shared with you how to read Request Path parameters, Query String parameters, and Form data. In this tutorial, you will learn how to read JSON from HTTP Post request body in Spring Boot application.
To read the body of an HTTP Post request, we will use the @RequestBody
annotation provided by the Spring framework.
@RequestBody Annotation
When a client sends an HTTP request to a Spring application, the request may contain a request body with data in a specific format, such as JSON or XML. The @RequestBody
annotation tells Spring to convert the request body data into an object of the specified type and pass it as a parameter to the method.
@PostMapping(path="/users") public ResponseEntity createUser(@RequestBody User user) { return ResponseEntity.ok(HttpStatus.OK); }
This code is an example of a Spring Web MVC Controller method that maps to a HTTP POST request for the /users
resource. The method has a single parameter, which is annotated with @RequestBody
, indicating that the method expects the HTTP request body to be mapped to a Java object of type User
. The User
object is created from the JSON payload that is sent as the body of the HTTP request.
The method returns a ResponseEntity
object with a HttpStatus
of OK. This response indicates that the request was successful, and the server is sending an empty response body with a 200 OK status code. This code can be used as a starting point for creating a RESTful API endpoint that accepts and processes JSON payloads.
When we use the @RequestBody annotation in Spring Framework, the content of the HTTP body is read and mapped to the Java object used as the method argument.
In order for Spring Framework to map JSON key-value pairs to the properties in the User class, the User class must have property names that exactly match those in the JSON payload.
public class User { private String firstName; private String lastName; private String email; private String password; private String repeatPassword; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRepeatPassword() { return repeatPassword; } public void setRepeatPassword(String repeatPassword) { this.repeatPassword = repeatPassword; } }
I hope this tutorial has been helpful to you. If you want to learn more about building web applications with Spring Framework, please check out the Spring Web MVC category.
Can we map JSON payload to nested Java objects using @RequestBody?
Yes, it is possible to map JSON payload to nested Java objects using @RequestBody. You can define nested classes within your main Java class and use them as method arguments with @RequestBody.
Let’s say you have a JSON payload like this:
{ "name": "John Doe", "age": 30, "address": { "street": "123 Main St", "city": "Anytown", "state": "CA", "zip": "12345" } }
And you have Java classes like this:
public class User { private String name; private int age; private Address address; // getters and setters } public class Address { private String street; private String city; private String state; private String zip; // getters and setters }
You can map the JSON payload to a User
object using @RequestBody
like this:
@PostMapping("/users") public ResponseEntity<User> createUser(@RequestBody User user) { // code to create user return ResponseEntity.ok(user); }
When the createUser
method is called with the JSON payload, Spring will automatically map the JSON properties to the corresponding fields in the User
object, including the nested Address
object.
Note that the property names in the JSON payload must match the field names in the Java classes for the mapping to work properly. If they don’t match, you can use the @JsonProperty
annotation to specify the mapping between the JSON property and the Java field.
Can I use @RequestBody with a collection or array of objects?
Yes, you can use the @RequestBody
annotation with a collection or array of objects in Spring MVC or Spring Boot applications.
When you use @RequestBody
with a collection or array of objects, Spring will automatically convert the incoming JSON array into a corresponding Java collection or array.
Here’s an example of how you can use @RequestBody
with a collection of objects:
@PostMapping("/users") public ResponseEntity<String> addUser(@RequestBody List<User> users) { // Process the list of users return ResponseEntity.ok("Users added successfully"); }
In this example, the @RequestBody
annotation is used with a List<User>
parameter. When a POST request is made to the “/users” endpoint with a JSON array of user objects in the request body, Spring will automatically map the JSON to a List<User>
object.
Similarly, you can use @RequestBody
with an array of objects:
@PostMapping("/products") public ResponseEntity<String> addProducts(@RequestBody Product[] products) { // Process the array of products return ResponseEntity.ok("Products added successfully"); }
In this example, the @RequestBody
annotation is used with a Product[]
parameter. When a POST request is made to the “/products” endpoint with a JSON array of product objects in the request body, Spring will automatically map the JSON to a Product[]
array.
Note that when using @RequestBody
with a collection or array of objects, the incoming JSON data must be in a specific format. For example, if you’re using JSON to send an array of User
objects, the JSON data should look something like this:
[ { "name": "John", "email": "[email protected]" }, { "name": "Jane", "email": "[email protected]" } ]
Overall, using @RequestBody
with a collection or array of objects in Spring is a powerful feature that can help you easily process and validate large amounts of data sent in HTTP requests.
How can we handle errors when using @RequestBody?
To handle errors when using @RequestBody
, you can use Spring’s built-in exception handling mechanisms. Spring provides several annotations and classes that allow you to handle exceptions and return appropriate error responses to clients.
One way to handle errors when using @RequestBody
is to use the @ExceptionHandler
annotation to define methods that handle specific exceptions. For example, you can define a method that handles HttpMessageNotReadableException
to handle cases where the request body cannot be read:
@ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { return ResponseEntity.badRequest().body("Invalid request body"); }
In this example, the @ExceptionHandler
annotation is used to define a method that handles HttpMessageNotReadableException
. When this exception is thrown, Spring will call this method and return a 400 Bad Request
response with a message indicating that the request body is invalid.
Another way to handle errors when using @RequestBody
is to use the @Valid
annotation to validate incoming data against constraints defined in your Java classes. For example, you can define a User
class with validation constraints on its fields:
public class User { @NotNull @Size(min = 3, max = 20) private String username; @NotNull @Email private String email; // Getters and setters }
In this example, the @NotNull
and @Size
annotations are used to define constraints on the username
field, while the @NotNull
and @Email
annotations are used to define constraints on the email
field.
When you use @Valid
with @RequestBody
, Spring will automatically validate incoming data against the constraints defined in your Java classes. If the data is invalid, Spring will throw a MethodArgumentNotValidException
exception, which you can handle using @ExceptionHandler
.
@PostMapping("/users") public ResponseEntity<String> addUser(@Valid @RequestBody User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // Handle validation errors } // Process the user return ResponseEntity.ok("User added successfully"); }
In this example, the @Valid
annotation is used to validate the incoming User
object against the constraints defined in the class. The BindingResult
parameter is used to access any validation errors that may have occurred. If validation errors exist, you can handle them in your controller method and return an appropriate error response.