Валидация объектов на основе правил-аннотаций для OneScript.
Библиотека позволяет описывать ограничения прямо на свойствах объектов через аннотации и выполнять проверку одним вызовом валидатора. Поддерживается проверка вложенных объектов, настраиваемые сообщения и простое расширение набора правил.
Для навигации по коллекциям используйте переключающую аннотацию &ДляКаждого:
&ДляКаждого("Значение")— переключает контекст на элементы коллекции (значение режима можно опустить)&ДляКаждого("Ключ")— переключает контекст на ключи коллекции (только для коллекций, итерируемых как КлючИЗначение)
- OneScript 1.9.2 или выше
- Через OPM (OneScript Package Manager):
opm install validate- Локально в проект: добавьте зависимость в ваш packagedef:
.ЗависитОт("validate", "0.1.0")Опишите ограничения аннотациями на полях вашего объекта:
&Заполнено(Сообщение = "Произвольное сообщение")
Перем Поле1 Экспорт;
&Заполнено
Перем Поле2 Экспорт;
&Минимум(-10)
&Максимум(10)
Перем Поле3 Экспорт;
&Валидно
Перем ВложенныйОбъект Экспорт;
&Тип("Число")
Перем Поле4 Экспорт;
// Элементы массива — строки
&Тип("Массив")
&ДляКаждого
&Тип("Строка")
Перем КоллекцияСтрок Экспорт;
// Значения структуры — числа
&Тип("Структура")
&ДляКаждого
&Тип("Число")
Перем СтруктураЧисел Экспорт;
// Ключи соответствия — числа
&Тип("Соответствие")
&ДляКаждого("Ключ")
&Тип("Число")
Перем СоответствиеЧисловыхКлючей Экспорт;Выполните валидацию и выведите ошибки:
Валидатор = Новый Валидатор;
Объект = Новый ТестовыйОбъект; // ваш класс с аннотациями
Результат = Валидатор.Валидировать(Объект);
Если Результат.Количество() > 0 Тогда
Сообщить(Валидатор.ОписаниеОшибокВалидации(Результат));
КонецЕсли;Пример строки в отчете об ошибках:
[filled]: Объект: <ТипОбъекта>, Свойство: Поле2, Сообщение: Значение не заполнено
Создайте класс с аннотациями валидации:
// Класс ПользовательДанные.os
&Заполнено(Сообщение = "Имя пользователя обязательно для заполнения")
Перем Имя Экспорт;
&Заполнено
&Минимум(18)
&Максимум(120)
Перем Возраст Экспорт;
&Заполнено
Перем Email Экспорт;
&Минимум(0)
&Максимум(100000)
Перем Зарплата Экспорт;
&Истина
Перем Активен Экспорт;// Создаем валидатор
Валидатор = Новый Валидатор;
// Сначала валидируем корректные данные
Пользователь = Новый ПользовательДанные;
Пользователь.Имя = "Иван Иванов";
Пользователь.Возраст = 30;
Пользователь.Email = "ivan@example.com";
Пользователь.Зарплата = 50000;
Пользователь.Активен = Истина;
РезультатВалидации = Валидатор.Валидировать(Пользователь);
// Проверяем результат - для корректных данных ошибок не будет
Если РезультатВалидации.Количество() = 0 Тогда
Сообщить("Данные корректны! Валидация прошла успешно.");
Иначе
Сообщить("Неожиданные ошибки при валидации корректных данных");
КонецЕсли;
// Теперь валидируем некорректные данные
НекорректныйПользователь = Новый ПользовательДанные;
НекорректныйПользователь.Имя = ""; // Пустое имя
НекорректныйПользователь.Возраст = 15; // Меньше минимума
НекорректныйПользователь.Зарплата = 150000; // Больше максимума
НекорректныйПользователь.Активен = Ложь; // Должно быть Истина
РезультатВалидации = Валидатор.Валидировать(НекорректныйПользователь);
// Выводим все ошибки
Если РезультатВалидации.Количество() > 0 Тогда
Сообщить("Найдено нарушений: " + РезультатВалидации.Количество());
Сообщить(Валидатор.ОписаниеОшибокВалидации(РезультатВалидации));
Иначе
Сообщить("Ошибка: валидация должна была найти нарушения");
КонецЕсли;// Создаем объект с ошибками
Пользователь = Новый ПользовательДанные;
Пользователь.Возраст = 200; // Превышает максимум
// Остальные поля не заполнены
РезультатВалидации = Валидатор.Валидировать(Пользователь);
// Обрабатываем каждое нарушение отдельно
Для Каждого Нарушение Из РезультатВалидации Цикл
ИмяСвойства = Нарушение.ИмяСвойства();
Сообщение = Нарушение.Сообщение();
КодОшибки = Нарушение.Код();
// Можно обрабатывать разные типы ошибок по-разному
Если КодОшибки = "filled" Тогда
Сообщить("Поле не заполнено: " + ИмяСвойства + " - " + Сообщение);
ИначеЕсли КодОшибки = "max" Тогда
Сообщить("Превышен максимум для поля: " + ИмяСвойства + " - " + Сообщение);
ИначеЕсли КодОшибки = "min" Тогда
Сообщить("Значение меньше минимума для поля: " + ИмяСвойства + " - " + Сообщение);
Иначе
Сообщить("Ошибка валидации [" + КодОшибки + "]: " + ИмяСвойства + " - " + Сообщение);
КонецЕсли;
КонецЦикла;// Класс ПользовательДанные.os (сокращенная версия)
&Заполнено
Перем Имя Экспорт;
&Валидно // Эта аннотация указывает, что нужно валидировать вложенный объект
Перем Адрес Экспорт;
// Класс Адрес.os
&Заполнено
Перем Город Экспорт;
&Заполнено
&Минимум(100000)
&Максимум(999999)
Перем Индекс Экспорт;
// Создаем пользователя с адресом
Пользователь = Новый ПользовательДанные;
Пользователь.Имя = "Петр Петров";
// Создаем адрес с ошибкой
Адрес = Новый Адрес;
Адрес.Город = "Москва";
Адрес.Индекс = 12345; // Меньше минимума
Пользователь.Адрес = Адрес;
// Валидация проверит и основной объект, и вложенный
// благодаря аннотации &Валидно у поля Адрес
РезультатВалидации = Валидатор.Валидировать(Пользователь);
Если РезультатВалидации.Количество() > 0 Тогда
Сообщить("Ошибки валидации:");
Сообщить(Валидатор.ОписаниеОшибокВалидации(РезультатВалидации));
КонецЕсли;&Заполнено(Сообщение = "...")— значение поля должно быть заполнено. Код нарушения:filled.&Истина— булево значение должно быть Истина. Код нарушения:true.&Ложь— булево значение должно быть Ложь. Код нарушения:false.&Минимум(<число>)— значение не меньше минимума. Код нарушения:min.&Максимум(<число>)— значение не больше максимума. Код нарушения:max.&Тип(<строка>)— значение должно иметь указанный тип. Код нарушения:type.&Валидно— рекурсивная проверка вложенного объекта. Код нарушения:valid.
Переключение контекста коллекций задаётся аннотацией &ДляКаждого; её можно указывать несколько раз для вложенных коллекций.
Сообщение об ошибке можно переопределить параметром аннотации Сообщение.
- Элементы массива в диапазоне 0..10:
&Тип("Массив")
&ДляКаждого
&Тип("Число")
&Минимум(0)
&Максимум(10)
Перем МассивЧиселСДиапазоном Экспорт;- Ключи соответствия больше 5 (минимум 6):
&Тип("Соответствие")
&ДляКаждого("Ключ")
&Тип("Число")
&Минимум(6)
Перем СоответствиеКлючиБольше5 Экспорт;Примечание: при &ДляКаждого("Ключ") для коллекций без ключей (например, Массив) будет выброшено исключение.
- Конструктор валидатора поддерживает подмену фабрики валидаций и контейнера аннотаций:
Валидатор = Новый Валидатор(МояФабрикаВалидаций, МойКонтейнерАннотаций);- По умолчанию используется
СтандартнаяФабрикаВалидаций, где назначено соответствие аннотаций и классов валидаций (ВалидацияОграниченияЗаполнено,...Минимум,...Максимум,...Истина,...Ложь,...Тип,...Валидно). - Можно добавлять собственные аннотации в контейнер и свои реализации классов валидаций/ограничений.
В проект включены авто-тесты на 1testrunner. Запустить можно так:
oscript tasks/test.osРезультаты в формате JUnit сохраняются в каталоге out.
Для прогона тестов со сбором покрытия используйте задачу из tasks/coverage.os:
oscript tasks/coverage.osСкрипт сохранит статистику в out/stat.json и сформирует отчеты:
out/genericCoverage.xml— Generic Coverage (используется Sonar)out/cobertura.xml— отчет в формате Cobertura (используется плагином Coverage Gutters в VSCode)
Этот проект лицензируется под лицензией MIT. Подробности см. в файле LICENSE.md.