Search code examples
javaspringjacksonpolymorphismdto

Get Derived DTO From Base Class Request Body DTO


I try to get derived class fields from methods response body. Request body parameter is type of base class. Request comes with derived class fields but I can't cast it to derived class.

Here is my controller method and DTO classes:

Method:

 @PostMapping("/{code}")
    public ResponseEntity<PromotionDto> createPromotion(@PathVariable String code, @RequestBody PromotionDto promotion){
        if(PromotionTypeEnum.ORDER_THRESHOLD_DISCOUNT.equals(promotion.getPromotionType())) {
            promotionService.createPromotion(orderThresholdDiscountPromotionConverter.toEntity((OrderThresholdDiscountPromotionDto)promotion));
        }
        return ResponseEntity.ok(promotion);
    }

Base class DTO:

import dto.base.BaseDto;
import promotionservice.PromotionTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PromotionDto extends BaseDto {
    private String code;
    private String title;
    private String description;
    private PromotionTypeEnum promotionType;

}

Derived class DTO:

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class OrderThresholdDiscountPromotionDto extends PromotionDto {
    private Double thresholdTotal;
    private Double discountPrice;
    private String messageFired;
    private String messageCouldHaveFired;
}

Request JSON is:

{
    "code":"qwewe",
    "title":"qwewe",
    "description":"qwewe",
    "promotionType":"ORDER_THRESHOLD_DISCOUNT",
    "thresholdTotal":1.3,
    "discountPrice":"12.5",
    "messageFired":"qwewe",
    "messageCouldHaveFired":"qwewe"

}

as result, service returns error:

{
"type": "https://www.jhipster.tech/problem/problem-with-message",
"title": "Internal Server Error",
"status": 500,
"detail": "promotion.PromotionDto cannot be cast to promotion.OrderThresholdDiscountPromotionDto",
"path": "/api/promotionresults/qwewe",
"message": "error.http.500"

}

My question is: is there any way, library, annotation etc. to get the derived class instance from request ?


Solution

  • Use Jackson inheritance feature. Annotate PromotionDto class as below:

    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "promotionType")
    @JsonSubTypes({
        @Type(value = OrderThresholdDiscountPromotionDto.class, name = "ORDER_THRESHOLD_DISCOUNT"),
    })
    class PromotionDto {
    

    and remove:

    private PromotionTypeEnum promotionType;
    

    property. It will be handled automatically by Jackson. In controller you will be able to use instanceof.