Как проверить тип «java.lang.Boolean» при загрузке Spring

У меня есть логическое поле, которое я хочу проверить, чтобы иметь только значение «истина» или «ложь» (без кавычек). Но это поле также допускает «истину» или «ложь» в качестве значения (с кавычками), которое я хочу ограничить.

Я попытался использовать аннотацию @Pattern для соответствия этим значениям. Но у меня следующая ошибка:

javax.validation.UnexpectedTypeException: HV000030: Не удалось найти средство проверки для ограничения 'javax.validation.constraints.Pattern', проверяющего тип 'java.lang.Boolean'. Проверьте конфигурацию на «перезапускаемый»

Мой код:

@Pattern(regexp = "^(true|false)$", message = "restartable field allowed input: true or false")
private Boolean restartable;

Что я должен делать? Есть ли другой способ преодолеть эту проблему? Заранее спасибо.


person Nobita    schedule 30.05.2019    source источник
comment
Как логическое значение может иметь другое значение? Логическое значение не является строкой. Он не содержит символов.   -  person JB Nizet    schedule 30.05.2019
comment
Pattern аннотация проверяет CharSequence, а не Boolean объект в соответствии с документацией: docs.oracle.com/javaee/7/api/javax/validation/constraints/ Вам нужно будет изменить свой тип на String, чтобы использовать Pattern. В качестве альтернативы вы можете создать свой собственный валидатор или проверить, существует ли уже логический валидатор.   -  person pandaadb    schedule 30.05.2019
comment
@JBNizet Но он принимает true как строку.   -  person Nobita    schedule 30.05.2019
comment
@Nobita, нет. Эти аннотации являются аннотациями проверки bean. Они используются для проверки вашего бина. Таким образом, все, что видит валидатор, — это объект типа Boolean. Он не видит ни одной строки. То, что преобразует строку в логическое значение, не имеет ничего общего с проверкой бина. Это парсер JSON. Если вы хотите отклонить строковые значения для логических полей, вам нужно настроить синтаксический анализатор JSON, а не проверку бина.   -  person JB Nizet    schedule 30.05.2019
comment
@JBNizet Как я могу настроить парсер Json для обработки этого? Я использую класс Jackson ObjectMapper.   -  person Nobita    schedule 30.05.2019
comment
Возможно, написав собственный десериализатор для логических значений.   -  person JB Nizet    schedule 31.05.2019


Ответы (3)


вы можете использовать утверждения @NotNull и @AssertTrue или @AssertFalse, присутствующие в javax.validation, если цель состоит в том, чтобы обеспечить ненулевое и истинное значение.

https://docs.oracle.com/javaee/7/tutorial/bean-validation001.htm

@NotNull
@AssertTrue
private Boolean restartable;

Аннотации Not Null будет достаточно, если значение может быть либо истинным, либо ложным, поскольку логические значения в Java могут иметь только два значения.

person Technoshaft    schedule 30.05.2019
comment
Но это ограничит поле только true. Верно? - person Nobita; 30.05.2019
comment
Правильно, извините. Если я неправильно понял, но если значение может быть истинным или ложным, проверки не будет достаточно, так как если вы попытаетесь передать строку или число в эту переменную, произойдет сбой. - person Technoshaft; 30.05.2019
comment
Я пробовал, но он позволяет true как строку, которую я хочу ограничить. - person Nobita; 30.05.2019
comment
Я предполагаю, что вы используете этот класс как десериализованную версию веб-запроса. В этом случае все параметры и тело запроса являются строковыми. Java-бин создаст соответствующий тип данных, анализируя только эту строку. - person Technoshaft; 30.05.2019

У меня была аналогичная проблема с проверкой формы логического значения, где технически я хотел, чтобы клиент только передал либо true, либо false, никаких других значений, чтобы убедиться, что они поняли, что на самом деле передают эти значения, а не передают целое число и мой код работает на основе интерпретируемого значения false (Boolean.valueOf() возвращает false практически для всего, кроме true).

Чтобы прояснить постановку задачи, поскольку некоторые люди кажутся немного запутанными, логическая проверка здесь не работает, потому что они могут пройти

{...
"value":8675309,
...}

где значение ДОЛЖНО быть логическим (но явно передается как int), однако валидатор/преобразователь просто запускает Boolean.valueOf() для переданного объекта, что в этом случае приведет к ложному результату, что может привести к последующей логике и изменениям что клиент НЕ ожидал (т. е. если логическое значение было чем-то вроде keepInformation, этот вышеприведенный сценарий мог привести к тому, что пользователь потерял всю свою информацию, потому что форма не была правильно проверена, и вы, возможно, оказались на крючке, поскольку клиент не технически сказать keepInformation:false)

В любом случае, чтобы бороться с этим, я обнаружил, что самым простым способом было сохранить логическое значение в виде строки, подобной такой

    @NotNull
    @Pattern(regexp = "^true$|^false$", message = "allowed input: true or false")
    private String booleanField;

Я протестировал это регулярное выражение, и оно будет проходить ТОЛЬКО для значения: true/true или значения: false/false, оно не будет работать с дополнительными кавычками (value:\true\), пробелами (value:true) и всем остальным, что не соответствует тому, что я написал выше.

Затем в вашем собственном геттере в этом объекте данных вы можете самостоятельно запустить логическое преобразование для дальнейшего использования.

    public boolean isSomething() {
        return Boolean.valueOf(booleanField);
    }
person Logan Smith    schedule 23.07.2020

Почему вы используете проверку текста в логическом поле? вот что пишет ошибка.

Я думаю, было бы разумнее проверить, является ли он нулевым или нет (используйте @NotNull); если он не равен нулю, то, безусловно, это допустимое логическое значение, по определению оно не может иметь никакого другого значения, кроме истинного или ложного. С другой стороны, если он равен нулю, то это, вероятно, ошибка, которую вы хотите обнаружить.

person Óscar López    schedule 30.05.2019
comment
Если вы пытаетесь избежать нулевых значений, просто используйте примитив boolean вместо класса Boolean, поскольку примитивы на самом деле не могут быть нулевыми. - person CasualViking; 30.05.2019
comment
Это правда, однако любое значение как String будет проходить через valueOf при синтаксическом анализе (я полагаю). Таким образом, логическое значение будет доступно, но значение this is test все равно выдаст false, а не выдаст соответствующую ошибку. - person pandaadb; 30.05.2019