在 Spring Boot 中 Jackson 之前验证输入

g3b*_*blv 5 spring hibernate-validator jackson spring-boot

我使用 Spring Boot 构建了一个 REST 端点。JSON被发布到端点。杰克逊转换了JSON给我一个对象。

看起来JSON像这样:

{
    "parameterDateUnadjusted": "2017-01-01",
    "parameterDateAdjusted": "2017-01-02"
}
Run Code Online (Sandbox Code Playgroud)

Jackson 将 转换JSON为基于此类的对象:

public class ParameterDate {

    @NotNull(message = "Parameter Date Unadjusted can not be blank or null")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date parameterDateUnadjusted;
    @NotNull(message = "Parameter Date Adjusted can not be blank or null")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date parameterDateAdjusted;
    private Date parameterDateAdded;
    private Date parameterDateChanged;
}
Run Code Online (Sandbox Code Playgroud)

这一切都很好。我遇到的问题是我想在杰克逊转换数据之前验证数据。例如,如果我发布

{
    "parameterDateUnadjusted": "2017-01-01",
    "parameterDateAdjusted": "2017-01-40"
}
Run Code Online (Sandbox Code Playgroud)

其中parameterDateAdjusted不是有效日期(没有包含 40 天的月份)。杰克逊将其转换为2017-02-09. 解决这个问题的一种方法是拥有一个只有字符串的类,我们称之为ParameterDateInput。使用 Hibernate Validator 验证parameterDateInput对象中的每个字段,然后将parameterDateInput对象复制到parameterDate每个字段具有正确类型的位置(日期是类型Date而不是类型String)。对我来说,这看起来不是一个非常优雅的解决方案。我还有其他方法可以解决这个问题吗?当数据发布为 时,Spring Boot 中通常如何验证数据JSON?我希望能够向用户/客户端发回一条消息,告知正在发布的数据有什么问题。

Sta*_*avL 0

有一种方法可以检查日期。setLenient()方法

public static boolean isValidDate(String inDate, String format) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(format);
    dateFormat.setLenient(false);
    try {
      dateFormat.parse(inDate.trim());
    } catch (ParseException pe) {
      return false;
    }
    return true;
 }
Run Code Online (Sandbox Code Playgroud)

只需定义自己的注释来验证值

@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = MyDateFormatCheckValidator.class)
@Documented
public @interface MyDateFormatCheck {
    String pattern();
...
Run Code Online (Sandbox Code Playgroud)

和验证器类

public class MyDateFormatCheckValidator implements ConstraintValidator<MyDateFormatCheck, String> {

    private MyDateFormatCheck check; 
    @Override
    public void initialize(MyDateFormatCheck constraintAnnotation) {
        this.check= constraintAnnotation;
    }

    @Override
    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
        if ( object == null ) {
            return true;
        }

        return isValidDate(object, check.pattern());
    }
}
Run Code Online (Sandbox Code Playgroud)