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

Joi — это инструмент на основе JavaScript для проверки данных, который экономит нам время и усилия, связанные с написанием кода проверки самостоятельно. Он основан на схеме. Это означает, что вы определяете свою собственную схему для данных, которые хотите проверить, определяя форматы, обязательные поля, ограничения и максимальные/минимальные диапазоны, и вы проверяете свой объект данных JSON, используя эти схемы.

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

Давайте начнем:

Для этого вам нужно будет установить Node.js, так как мы будем работать в среде JavaScript.

Если у вас нет знаний node.js, не нужно паниковать. Мы не будем использовать node.js больше, чем для установки библиотеки через npm и запуска нашего кода.

Чтобы установить Node.js, если у вас его еще нет, перейдите на https://nodejs.org/, скачайте Node.js, подходящий для вашей ОС, и установите его.

Давайте начнем с создания новой папки для нашей работы и установки библиотеки joi.

md joidemo
cd joidemo
npm init
npm install joi

Вышеупомянутое сделает следующее:

  1. создайте новый каталог с именем joidemo (может отличаться в зависимости от вашей ОС)
  2. перейдите в новый каталог joidemo (может отличаться в зависимости от вашей ОС)
  3. инициировать новый пакет npm
  4. установить библиотеку joi с помощью npm

Я рекомендую использовать Visual Studio Code для написания кода. Вы можете скачать его, если у вас его нет, с https://code.visualstudio.com/.

Прежде чем мы начнем вводить код, давайте рассмотрим некоторые основы joi.

Схема Джой:

Прежде чем мы начнем использовать joi, нам нужно require() библиотеку joi.

const joi = require('joi');

Joi использует схему, которая является своего рода шаблоном объекта, который сообщает joi правила, которым необходимо следовать при проверке данных. Схема определяется следующим образом:

const schemaName = joi.object({
    dataPropertyName: [Joi validation options],
    dataProeprtyName: [Joi validation options],
    .
    .
    .
    dataProeprtyName: [Joi validation options]
})

Что-то похожее на определение объекта в JavaScript. Вы определяете имя объекта (имя схемы по вашему выбору), определяете свойства объекта и для каждого свойства определяете правила проверки.

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

const userSchema = joi.object({
    userName: joi.string().alphanum().min(6).max(10).required(),
    email: joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net', 'org'] }}),
    age: joi.number().min(18).max(50),
    dateOfBirth: joi.date().required()
});

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

Мы начали с определения свойства userName и указали, что это должна быть строка с joi.string(). Это говорит joi, что это свойство должно быть строкой. Например, это не может быть число. Кроме того, мы хотим, чтобы строка содержала буквенно-цифровые символы, поэтому мы использовали .alphanum(). Мы определили минимальную длину строки в 6 символов и максимальную в 10 с помощью .min(6) и .max(10). . Наконец, мы указываем, что это .required() и обязательное значение.

Мы определяем свойство электронной почты, которое также является .string(), и сообщаем joi, что оно должно быть .email(). Структура электронной почты будет иметь 2 сегмента minDomainSegments, а домен может быть .com, .net или .org с использованием tld: { allow: ['com', 'net', 'org'] }. Это означает, что .co или .info недействительны.

Свойство age определяется как .number()от 18 до 50. Значение меньше 18 или больше 50 недопустимо.

И, наконец, свойство dateOfBirth должно быть .date() и .required(). .

Как вы видели. мы объединяем несколько правил и ограничений для каждого элемента данных или свойства в одной строке. Существует так много способов проверить значение данных. Мы рассмотрим некоторые, и вы всегда можете обратиться к документации joi для получения дополнительной информации.

Джой Проверка:

Мы видели, как определить шаблон или схему проверки. Но как проверить наши данные?

Начнем с определения объекта данных и добавления к нему некоторых значений.

let myData = {
    userName: "JohnSmith", 
    email: '[email protected]',
    age: 20,
    dateOfBirth: '12-06-2000'  
}

Простой объект JS с 4 свойствами, и их имена совпадают с именами свойств в объекте схемы joi. Имена свойств, которые вы хотите проверить, должны совпадать с именами в схеме, включая регистр символов.

И для проверки этого объекта данных мы используем метод .validate() объекта схемы, который мы создали. Это будет выглядеть так.

let valResult = userSchema.validate(myData);

Приведенная выше инструкция получит результат проверки из метода .validate() схемы и присвоит его переменной valResult.

Давайте посмотрим на полный код index.js и добавим console.log(), чтобы увидеть результат.

В терминале VS Code или в командной строке выполните следующую команду:

node index

Это запустит код index.js. Вы должны увидеть следующее:

Результат, возвращаемый методом .validate() схемы, имеет два свойства объекта: значение и ошибка. Свойство объекта значения вернет проверенный объект данных. Свойство объекта ошибки возвращается только в том случае, если обнаружена ошибка проверки и оно содержит описания ошибок. Из приведенного выше результата мы можем видеть только свойство value, поскольку в наших данных нет ошибок проверки.

Простой. Не так ли? 😃

Теперь попробуйте изменить значения на недопустимые. Давайте сделаем возраст 65 лет и установим dateOfBirth как «1253–5678». Снова запустите индекс узла и проверьте результат.

Результат содержит ошибку, как и ожидалось. Он говорит "ValidationError: "возраст" должен быть меньше или равен 50". А как же дата рождения? это недопустимое значение не сообщается!

По умолчанию Joi отменяет проверку при первой ошибке, оставляя остальные свойства без проверки. Если нам нужно, чтобы все свойства проверялись, а обо всех ошибках сообщалось за один шаг проверки, нам нужно добавить это как параметр в команду проверки. для параметра abortEarly по умолчанию установлено значение true. Поэтому, чтобы проверить все свойства, установите для него значение false.

Замените строку команды проверки на приведенную ниже и повторите запуск.

let valResult = userSchema.validate(myData, {abortEarly: false});

Мы должны получить следующий результат.

Свойство ValidationError содержит все ошибки, о которых сообщается на данный момент. Но они находятся в одном строковом значении. Не так уж и практично, не так ли.

Нам нужно разделить ошибки для лучшего сообщения об ошибках. Как видите, свойство error возвращаемого результата проверки является объектом. Сообщенные ошибки собираются в свойстве details объекта error, и поскольку console.log показывает значения первого уровня, объект details отображается неправильно. Итак, давайте немного изменим команду console.log. Мы отобразим объект error возвращаемого результата. Замените строку console.log приведенной ниже.

console.log(valResult.error);

И мы получим следующий результат, повторно запустив скрипт .js с помощью команды node.

Обратите внимание, что объект details теперь также отображается в списке, и мы видим, что сообщается о двух ошибках. Один для возраста и один для даты рождения.

Если вы добавите к объекту данных свойства, которые не определены в схеме, проверка joi сообщит о них как о «не разрешенных». Попробуйте.

Проверка отдельных значений

Joi.validate() можно использовать для проверки одного значения. Посмотрите на приведенный ниже пример.

joi.string().max(6).validate('Hello');        // Valid
joi.string().max(6).validate('Hello World');  // Invalid.
joi.string().max(6).validate(123456);         // Invalid.

Правило проверки можно связать с .validate() для проверки одного значения. Если мы поместим каждый из них в console.log(), мы увидим результат проверки.

Joi.validate()не создает исключений и не прерывает поток выполнения, что означает, что при использовании .validate() мы имеем для проверки результатов и решения любых проблем проверки. Иногда нам нужны недопустимые входные данные для создания исключений, чтобы мы могли правильно их обработать.

Есть два метода joi, которые генерируют исключения, когда проверка возвращает недопустимые значения.

Джой.Утвердить ()

Joi.assert() создает исключение, когда проверка значения по схеме не удалась. Мы можем определить сообщение, которое будет отображаться в случае обнаружения недопустимого значения. Он имеет следующий синтаксис:

joi.assert(value, schema, [message], [options])

Пример:

joi.assert('Hello', joi.string().max(10), 'Invalid value passed');

инструкция по дрочке ()

Joi.attempt() похож на joi.assert() тем, что выдает исключение, когда проверка значения по схеме не удалась, и сообщение, отображаемое в случае ошибки. найдено недопустимое значение. Разница в том, что .attempt() возвращает допустимый объект, если значение(я) допустимы.

Он имеет следующий синтаксис:

let result = joi.attempt(value, schema, [message], [options])

Пример:

let result = joi.attempt('Hello', joi.string().max(10), 'Invalid value passed');
// result -> 'Hello'

дзёи.компиляция()

Схемы в joi могут быть записаны как литералы. Нравится:

const schemaDef = {
    userName: 'JohnSmith',
    age: 40,
    email: '[email protected]',
    dateOfBirth: '06-06-1980'
}

Это похоже на объект данных, не так ли? Это потому, что это объект данных. 😃

Чтобы объяснить вышесказанное, мы установили первое свойство, которое будет проверяться как строка с допустимым значением «JohnSmith». Любые другие значения будут недействительными. Аналогично joi.string.valid('JohnSmith').

Вторым свойством будет число с допустимым значением 40. Аналогично joi.number().valid(40).

Третье и четвертое свойства также определяются как строки с одним допустимым значением.

Этот метод хорош, если у нас есть предопределенные допустимые значения. Но как мы используем их в качестве схемы? Ответ заключается в компиляции определения в схему с помощью joi.compile(), как показано ниже.

Давайте создадим новый файл .js, назовем его «sch_comp.js» и поместим в него следующее.

Литералы схемы также могут быть определены как массивы возможных значений. Например, чтобы определить несколько допустимых значений для числового свойства, его можно определить, скомпилировать и использовать, как показано ниже:

// define the schema literals
const possibleValues = [10, 23, 40, 55];
// compile the literals into a schema object
const numSchema = joi.compile(possibleValues);
// use the schema to validate a value
let valResult = numSchema.validate(23);      // valid
valResult = numSchema.validate(50);          // invalid

Вышеприведенное аналогично определению объекта схемы, как показано ниже:

const numSchema = joi.number().valid(10, 23, 40, 55);

Это основное использование библиотеки проверки joi. Сейчас мы рассмотрим некоторые типы данных и методы проверки, а также некоторые их свойства проверки.

.валидатасинк()

Как и .validate(), этот метод схемы будет принимать значение для проверки и параметров проверки. Но, в отличие от метода .validation(), он не возвращает значение проверки. Скорее, он возвращает обещание, которое можно обработать с помощью .then() и .catch(). Ниже приведен пример.

.типы()

Начнем с .types(). Этот метод возвращает набор объектов, определяющих типы, приемлемые для joi. Это полезно, когда мы используем ярлыки для их типов, а не методы типа joi. Мы можем деконструировать типы, которые мы хотим использовать в нашей схеме. Посмотрите на приведенный ниже код.

// import the joi library
const joi = require('joi');
// deconstruct types stcing and number
const { string, number } = joi.types();
// use the deconstructed objcts rather than the type methods
const schema = joi.object({
    a: string.max(10),
    b: number.min(10).max(20)
});
// Let's validate using our new schema
console.log(schema.validate({a: 'Hello', b: 20}));

Просто и прямолинейно. Не так ли?

.любой()

Этот тип может соответствовать любому типу данных. Одним из полезных методов проверки .any() является .allow(). .allow() разрешает допустимость набора значений, указанных в качестве параметров, в дополнение к любым другим разрешенным значениям. Это более эффективно при использовании .valid() с .allow().

Предположим, у нас есть следующая схема, которая допускает только нечетные числа от 1 до 9.

const schema = joi.any().valid(1, 3, 5, 7, 9);

И мы хотим, чтобы 2 и 10 по какой-то причине тоже были действительными. Мы можем настроить приведенную выше команду следующим образом.

const schema = joi.any().valid(1, 3, 5, 7, 9).allow(2, 10);

Это позволит числам [1, 2, 3, 5, 7, 9, 10] быть допустимыми значениями.

.alter(цель)

Еще один полезный метод, применимый ко всем типам, а не только к any(), — метод .alter(). Это позволяет нам настроить схему на основе цели, заданной методом .tailor(). Давайте посмотрим на следующий пример.

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

Таким образом, первый проверенный объект будет действительным, но не второй проверенный объект. Но что, если мы хотим разрешить короткие значения для одних сред и разрешить длинные значения для других? Мы можем сделать это следующим образом:

Теперь у нас есть индивидуальные схемы, основанные на целевых значениях, которые необходимо проверить. Мы определили внутри схемы два варианта для каждого значения. Если он нацеливался на короткие значения с помощью .tailor(‘short’), он вернет схему с коротким условием проверки. И, если он нацеливался на длинные значения с помощью .tailor(‘long’), он вернет схему с условием длинной проверки. И мы создали новую схему из исходной, используя .tailor()указав желаемую цель в качестве аргумента.

.concat(схема)

Метод .concat() объединяет несколько схем и возвращает новую схему.

Объединенная схема должна быть одного типа. Например, схема типа .string() может быть объединена с другой схемой типа .string(). Схема типа объекта должна быть объединена со схемой типа объекта. И так далее. Объединение схемы объекта со схемой .string(), например, приведет к ошибке «Невозможно объединить объект типа с другим типом: строка».

// E.g. (1): string schema + string schema
const name1 = joi.string().min(5);
const name2 = joi.string().max(15).required();
const nameSchema = name1.concat(name2);
// result: joi.string().min(5).max(15).required()
// E.g. (2): object schema + object schema
const user1 = joi.object({
    fname: joi.string().min(6).max(15),
    lName: joi.string().min(6).max(15)
});
const user2 = joi.object({
    age: joi.number().min(18).max(50).required()
});
const schema = user1.concat(user2);
// result: joi.object({
//    fname: joi.string().min(6).max(15),
//    lName: joi.string().min(6).max(15),
//    age: joi.number().min(18).max(50).required()
// })

.custom(метод [, описание])

Иногда нам нужно реализовать собственный метод проверки с определенными настраиваемыми условиями. Joi позволяет нам создавать собственные методы и использовать их, как если бы они были частью методов проверки joi. Давайте посмотрим на приведенный ниже пример:

Так просто и прямолинейно. Дополнительные сведения о параметре helpers см. в разделе any.custom(method, [description]).

.описывать()

Используйте .describe() для отображения конфигурации схемы в целях отладки или для передачи описания схемы другим системам.

.ошибка(err_msg)

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

const strSchema = joi.string().min(3).error(new Error("Can't accept a string less than 3 characters in length.");

Это были некоторые из описанных здесь методов joi с примерами. Список очень длинный, но его стоит посмотреть и пройти. Дайте мне знать, если вам нужна дополнительная информация или объяснение любого из этих методов, упомянутых здесь или с сайта joi .dev.

Спасибо, что прочитали это, и не забудьте 👏 👏 👏 😃