如何强制Jackson调用控制器中对象(dto)中所有属性的Set方法?

时间:2018-08-08 02:36:09

标签: java spring-mvc spring-boot jackson

我在每个属性的集合中执行的控制器参数“命令”中有一些验证,问题是属性未通知,杰克逊没有调用set方法来进行验证。即使缺少属性,是否可以强制Jackson调用Set方法?

对于没有代理商字段的示例有效载荷:

{
   "bank": "237",
   "account": "20772-1",
   "taxId": "36456155800",
   "paidAmount": 30.00
}

我的控制器:

public Return confirmTransfer(@RequestBody RechargeTransferConfirmationCommand command) {
    System.out.println(command);
}

Java类:

public class RechargeTransferConfirmationCommand {

    public static final String ERR_INVALID_AGENCY = "Agency number can not be null.";

    private String bank;
    private String account;
    private String agency;
    private String taxId;

    public RechargeTransferConfirmationCommand(BigDecimal paidAmount, String bank, String account,
            String agency, String taxId) {

        setPaidAmount(paidAmount);
        setBank(bank);
        setAccount(account);
        setAgency(agency);
        setTaxId(taxId);
    }

    public void setRechargeId(RechargeId rechargeId) {
        assertArgumentNotNull(rechargeId, Recharge.ERR_RECHARGE_ID_INVALID);
        this.rechargeId = rechargeId;
    }

    private void setPaidAmount(BigDecimal paidAmount) {
        if (paidAmount == null || paidAmount.compareTo(BigDecimal.ZERO) < 0)
            throw new IllegalArgumentException(Recharge.ERR_INVALID_AMOUNT);
        this.paidAmount = paidAmount;
    }

    private void setBank(String bank) {
        assertArgumentNotEmpty(bank, TransferInformation.ERR_INVALID_BANK_NUMBER);
        this.bank = bank;
    }

    private void setAccount(String account) {
        assertArgumentNotEmpty(account, TransferInformation.ERR_INVALID_ACCOUNT);
        this.account = account;
    }

    private void setAgency(String agency) {
        assertArgumentNotEmpty(agency, ERR_INVALID_AGENCY);
        this.agency = agency;
    }

    private void setTaxId(String taxId) {
        assertArgumentNotEmpty(taxId, ERR_INVALID_TAX_ID);
        this.taxId = taxId;
    }

}

在这种情况下,对于每个字段,将调用set方法进行验证,除了未在有效负载中通知的代理字段外,它应立即引发方法assertArgumentNotEmpty中包含的异常。

3 个答案:

答案 0 :(得分:1)

是,杰克逊将不会调用未在有效负载中传递的字段的setter方法,如果要验证丢失的字段,则需要自定义Deserializer

class RechargeTransferConfirmationCommandDeserializer extends JsonDeserializer<RechargeTransferConfirmationCommand> {

@Override
public RechargeTransferConfirmationCommand deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    RechargeTransferConfirmationCommand responseModel = jp.readValueAs(RechargeTransferConfirmationCommand.class);

    RechargeTransferConfirmationCommand finalModel = new RechargeTransferConfirmationCommand();
    finalModel.set agency(responseModel. agency == null || age.trim().isEmpty() ? "agency" : responseModel.agency);

    return finalModel;
   }

}

您的模特应该是

@JsonDeserialize(using = DefaultModelDeserializer.class)
public class DefaultModel {

...
}

答案 1 :(得分:0)

还要在方法&&声明@JsonSetter中使用no args constructor

public RechargeTransferConfirmationCommand(){
}
@JsonSetter
    public void setRechargeId(RechargeId rechargeId) {
        assertArgumentNotNull(rechargeId, Recharge.ERR_RECHARGE_ID_INVALID);
        this.rechargeId = rechargeId;
    }

但是最好使用javax验证。查看this以获得详细信息。

另一种方式: 您可以使用一种方法编写所有验证并使用@AssertTrue:

@AssertTrue
public boolean isValid(){
//if all field is valid then return true;
return false;
}

答案 2 :(得分:0)

使用@JsonCreator解决了问题,谢谢大家的帮助

@JsonCreator
public RechargeTransferConfirmationCommand(@JsonProperty("paidAmount") BigDecimal paidAmount,
        @JsonProperty("bank") String bank, @JsonProperty("account") String account,
        @JsonProperty("agency") String agency, @JsonProperty("taxId") String taxId) {

    setPaidAmount(paidAmount);
    setBank(bank);
    setAccount(account);
    setAgency(agency);
    setTaxId(taxId);
}