0

I am doing a basic Login flow, where I expect my LoginRequest DTO to be one of three possible types, as described in the code snippet below. But I am having trouble using this in a @RequestBody because spring doesn't understand how to de-serialize it into an object.

// type definitions
    public sealed interface LoginRequest permits DefaultLogin, LoginWithEmail, LoginWithPhone {}
    public record DefaultLogin(@Min(1) int userId, @NotBlank String password) implements LoginRequest {}
    public record LoginWithEmail(@NotBlank String email) implements LoginRequest {}
    public record LoginWithPhone(@NotBlank String phoneNumber) implements LoginRequest {}

// controller
    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestBody @Valid LoginRequest loginRequest) {
        UserFlow.Authenticated login = userService.login(loginRequest);
        System.out.println("Authenticated: " + login.toString());
        return ResponseEntity.accepted().body(login.toString());
    }

I am getting the below error:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.example.testingdemo.Types.UserFlow$LoginRequest (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

Somjit
  • 2,503
  • 5
  • 33
  • 60
  • 1
    Spring uses jackson internally to serialize and deserialize. Jackson requires constructor or getter/setters to create an object. You need to use a concrete type and not an interface. Error mesage is pretty clear. – pvpkiran Nov 21 '22 at 09:43

0 Answers0