Spring: Bind values in x-www-form-urlencoded requests

Posted on Jan 30, 2024

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!