Использование валидации в Spring для ограничения поля ZonedDateTime тремя цифрами в миллисекунду - PullRequest
0 голосов
/ 11 марта 2019

У меня есть входной DTO в запросе Spring MVC, который я хочу проверить, в частности, поле ZonedDateTime должно содержать не более 3 цифр на уровне миллисекунд, то есть оно не может быть с точностью до наносекунд.Кроме этого, запрос ввода должен соответствовать формату даты и времени ISO.Я мог бы сделать поле строкой, а затем просто ограничить его регулярным выражением, но я предпочитаю сохранять его как ZonedDateTime, поэтому мне не нужно анализировать его снова.

Объект выглядит следующим образом:

@Data
public class MeasurementDTO {

    private ZonedDateTime date;
    @Digits(integer = 20, fraction = 8) private BigDecimal value;

}

И это вложенный DTO, в котором родительский объект выглядит как @RequestBody с аннотацией @Valid.

Я пробовал @JsonFormat, но не могу ограничитьмиллисекундная часть.Есть ли способ сделать это, или я должен просто разобрать это как строку, а затем разобраться с этим?Или даже просто оставить его в ZonedDateTime, а затем проверить наносекундный компонент, чтобы увидеть, есть ли он в пользовательском валидаторе?

Благодаря ответу Тима я вспомнил, что Java Date в любом случае не имеет большей точности, чем миллис,поэтому я обновил вопрос, чтобы использовать ZonedDateTime с точностью до наносекунды.Я хочу иметь возможность предупредить пользователя, если он попытается передать больше точности, если при использовании даты эта информация будет просто проглочена.

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Возможно, вы не считаете это полным ответом, но java.util.Date сохраняет точность только до миллисекунд, и не более того. Посмотрите ответ Джона Скита здесь или прочитайте исходный код для CalendarDate , который показывает, что у него нет ничего, кроме миллисекундной памяти.

Таким образом, нет смысла ограничивать Date точностью до миллисекунды с помощью валидации Hibernate, потому что сам тип уже имеет это ограничение.

0 голосов
/ 12 марта 2019

Я сделал это трудным путем с помощью специального валидатора. Я все еще приветствую ответы, которые делают это более кратким способом все же.

Вот мое решение:

Я добавил аннотацию @ ValidMeasurementInput

@Documented
@Constraint(validatedBy = MeasurementValidator.class)
@Target({TYPE, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface ValidMeasurementInput {

    String message() default "Invalid measurement input";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

И реализовал пользовательский валидатор

public class MeasurementValidator implements ConstraintValidator<ValidMeasurementInput, MetricsDTO> {

    @Override
    public boolean isValid(MetricsDTO metricsDTO, ConstraintValidatorContext context) {
        ...
    }
}

Где-то в этом классе среди некоторых других проверок есть этот код:

   int nano = measurementDTO.getDate().getNano();
   int remainderAfterMillis = nano % 1000000;
   if (remainderAfterMillis != 0)
       valid = false;

И, конечно, я добавил @ValidMeasurementInput к своему DTO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...