wesleyy
wesleyy

Reputation: 2735

Spring @RequestBody inheritance

I've read several posts where this was tried to be explained, but I couldn't get it working. I have a scenario where the input JSON to my service can be of several subtypes. Basically, I have a base class UserDto and then ClientDto and OwnerDto both of which extend from UserDto. I'd like to achieve that the controller is able to resolve concrete subtype of UserDto into object of the correct class. So something like this.

@ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public void doSomething(@RequestBody UserDto user) {
        ClientDto client = (ClientDto) user;
        // do something
    }

I tried something like this. Basically I want to determine the type of the concrete object by the field profileType which is of type enum ProfileType with values OWNER and CLIENT.

UserDto.java

@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "profileType", visible = true)
@JsonSubTypes({
    @JsonSubTypes.Type(value = ClientDto.class, name = "Client"),
    @JsonSubTypes.Type(value = OwnerDto.class, name = "Owner")
})
public class UserDTO {

    @NotNull
    @Size(min = 0, max = 256)
    private ProfileType profileType;

    @NotNull
    @Size(min = 0, max = 512)
    private String email;

    // ...
}

ClientDto.java

public class ClientDto extends UserDto {

    private Integer salary;

    private Integer efficiency;

    // ... 
}

I tried posting the following JSON to this end-point.

{
        "email": "[email protected]",
        "profileType": "CLIENT",
        "salary": "100",
        "efficiency": "99"
    }

And I expected this to be resolved to a type of ClientDto. Instead, I only got a 400 Bad Request error.

The questions are:

  1. How do I fix this, and have the @RequestBody inheritance working?
  2. Is there a way to specify annotations on the subtypes rather than defining all of them on the supertype?

Upvotes: 10

Views: 11780

Answers (1)

pvpkiran
pvpkiran

Reputation: 27018

Couple of mistakes in your code.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "profileType", visible = true)
@JsonSubTypes({
    @JsonSubTypes.Type(value = ClientDto.class, name = "CLIENT"),
    @JsonSubTypes.Type(value = OwnerDto.class, name = "OWNER")
})
public class UserDTO {
 .....
}
  1. You said ProfileType enum has OWNER and CLIENT. But you have specified in JsonSubTypes.Type as Client and Owner. hence doesn't match
  2. change JsonTypeInfo.Id.CLASS to JsonTypeInfo.Id.NAME

Upvotes: 9

Related Questions