Spring: Bind values in x-www-form-urlencoded requests
In Spring Boot it’s not possible to map request field names to property fields with @JsonProperty when a request method is consuming application/x-www-form-urlencoded type of requests. The reason is that there’s no JSON payload in the body to consume.
To resolve this @BindParam has to be used.
Note This feature is available since Spring 6.1. and Spring Boot 3.2.0.
Check the following working example:
@RestController
@RequestMapping(path = "/user/")
public class UserController {
@PostMapping(value = "login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String login(User user) {
// user.username is not null
return "Logged in!";
}
@Data
@AllArgsConstructor
public static class User {
@BindParam("user_name")
private String username;
private String password;
}
}
The username property will get the value of the user_name field passed in the request. That behaves the same as using the @JsonProperty in requests of the type application/json with Jackson.
A cURL request can look like this:
curl -X POST --location "http://localhost:8080/user/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'user_name=dkwr&password=secret'
Usage without Lombok
When not using Lombok the @BindParam annotation can be used in the constructor:
public User(@BindParam("user_name") String username, String password) {
this.username = username;
this.password = password;
}
What to consider when using Lombok
When using Lombok, this can be used with @Builder, too. But not with @RequiredArgsConstructor!