🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Joi 教程 > 原文: [http://zetcode.com/javascript/hapijoi/](http://zetcode.com/javascript/hapijoi/) Joi 教程展示了如何使用 Hapi Joi 模块验证 JavaScript 中的值。 ## Joi Hapi Joi 是一种对象模式描述语言,也是 JavaScript 对象的验证器。 使用 Hapi Joi,我们可以为 JavaScript 对象(存储信息的对象)创建蓝图或架构,以确保验证关键信息。 Hapi 是一个易于使用的以配置为中心的框架,具有对输入验证,缓存,认证以及用于构建 Web 和服务应用的其他基本函数的内置支持。 ## Joi 安装 首先,我们安装库。 ```js $ node -v v11.5.0 ``` 我们使用 Node 版本 11.5.0。 ```js $ npm init -y $ npm i @hapi/js ``` 我们启动项目,并使用`nmp i @hapi/joi`安装 Hapi Joi。 ## Joi 验证 验证通过`validate()`函数执行: ```js validate(value, schema, [options], [callback]) ``` `value`是要验证的值,`schema`是验证模式。 `options`是验证选项。 在`abortEarly`选项停在第一个错误的验证,否则返回发现的所有错误。 默认为`true`。 `convert`选项尝试将值转换为所需的类型。 它也默认为`true`。 `callback`是使用签名`function(err, value)`的可选同步回调方法。 如果验证失败,则`err`包含错误原因,否则为`null`。 `value`是应用了任何类型转换和其他修饰符的值。 ## Joi 版本 在第一个示例中,我们打印 Hapi Joi 的版本。 `version.js` ```js const Joi = require('@hapi/joi'); console.log(Joi.version) ``` Joi 的版本存储在`Joi.version`中。 ```js const Joi = require('@hapi/joi'); ``` 我们包括 Hapi Joi 模块。 ```js $ node version.js 15.0.3 ``` 这是一个示例输出。 ## Joi 同步函数 在下面的示例中,我们在同步函数内部执行验证。 `sync_fun.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ username: Joi.string().required(), email: Joi.string().email().required() }); let username = 'Roger Brown'; let email = 'roger@example'; let data = { username, email }; Joi.validate(data, schema, (err, value) => { if (err) { console.log(err.details); } else { console.log(value); } }); ``` 我们有两个值可以验证:用户名和电子邮件。 ```js const schema = Joi.object().keys({ username: Joi.string().required(), email: Joi.string().email().required() }); ``` 这是验证模式。 用户名必须是字符串,并且是必需的。 该电子邮件必须是有效的电子邮件地址,并且也是必需的。 ```js let username = 'Roger Brown'; let email = 'roger@example'; let data = { username, email }; ``` 这是要验证的数据。 ```js Joi.validate(data, schema, (err, value) => { if (err) { console.log(err.details); } else { console.log(value); } }); ``` `Joi.validate()`使用提供的模式验证数据。 ```js $ node sync_fun.js [ { message: '"email" must be a valid email', path: [ 'email' ], type: 'string.email', context: { value: 'roger@example', key: 'email', label: 'email' } } ] ``` 这是示例输出。 ## Joi 返回值 在下一个示例中,我们不使用同步函数。 我们使用返回的值。 `ret_vals.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ username: Joi.string().required(), born: Joi.date().required() }); let username = 'Roger Brown'; let born = '1988-12-11'; let data = { username, born }; const { err, value } = Joi.validate(data, schema); if (err) { console.log(err.details); } else { console.log(value); } ``` 该示例验证两个值:用户名和生日。 ```js const { err, value } = Joi.validate(data, schema); ``` 使用`validate()`的另一种方法是获取其返回值。 ```js if (err) { console.log(err.details); } else { console.log(value); } ``` 根据返回的值,我们将打印错误详细信息或原始值。 ```js $ node ret_vals.js { username: 'Roger Brown', born: 1988-12-11T00:00:00.000Z } ``` 我们没有错误,因此会打印验证值。 ## Joi `abortEarly` 默认情况下,Joi 会在第一个错误时停止验证。 如果要获取所有错误,则必须将`abortEarly`选项设置为`true`。 `abort_early.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ username: Joi.string().min(2).max(30).required(), password: Joi.string().regex(/^[\w]{8,30}$/), registered: Joi.number().integer().min(2012).max(2019), married: Joi.boolean().required() }); let username = 'Roger Brown'; let password = 's#cret12'; let registered = '2011'; let married = false; let data = { username, password, registered, married }; let options = { abortEarly: false }; const { error, value } = Joi.validate(data, schema, options); if (error) { console.log(error.details); } else { console.log(value); } ``` 在示例中,我们将打印所有已发生的错误。 ```js const schema = Joi.object().keys({ username: Joi.string().min(2).max(30).required(), password: Joi.string().regex(/^[\w]{8,30}$/), registered: Joi.number().integer().min(2012).max(2019), married: Joi.boolean().required() }); ``` 我们有四个值可以验证。 ```js let options = { abortEarly: false }; const { error, value } = Joi.validate(data, schema, options); ``` 我们将`abortEarly`选项设置为`false`。 ```js $ node abort_early.js [ { message: '"password" with value "s#cret12" fails to match the required pattern: /^[\\w]{8,30}$/', path: [ 'password' ], type: 'string.regex.base', context: { name: undefined, pattern: /^[\w]{8,30}$/, value: 's#cret12', key: 'password', label: 'password' } }, { message: '"registered" must be larger than or equal to 2012', path: [ 'registered' ], type: 'number.min', context: { limit: 2012, value: 2011, key: 'registered', label: 'registered' } } ] ``` 我们有两个验证错误。 ## Joi `convert` Joi 默认情况下强制转换值; 要禁用投射,我们将`convert`选项设置为`false`。 `casting.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ timestamp: Joi.date().timestamp(), val: Joi.number() }); let val = '23543'; let timestamp = 1559761841; let data = { val, timestamp }; const { error, value } = Joi.validate(data, schema); if (error) { console.log(error.details); } else { console.log(value); } ``` 在示例中,我们有两个 Joi 自动转换的值。 ```js let val = '23543'; let timestamp = 1559761841; ``` 该字符串将强制转换为数字,而时间戳则转换为 ISO 字符串。 ```js $ node casting.js { val: 23543, timestamp: 1970-01-19T01:16:01.841Z } ``` 这是输出。 ## Joi 验证数字 使用`Joi.number()`,我们可以验证数字。 `numbers.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ age: Joi.number().min(18).max(129), price: Joi.number().positive(), experience: Joi.number().greater(5) }); let age = 35; let price = -124.3; let experience = 6; let data = { age, price, experience }; const { error, value } = Joi.validate(data, schema); if (error) { console.log(error.details); } else { console.log(value); } ``` 在示例中,我们验证了三个数字。 ```js const schema = Joi.object().keys({ age: Joi.number().min(18).max(129), price: Joi.number().positive(), experience: Joi.number().greater(5) }); ``` `age`值必须是 18-129 之间的数字。 `price`必须为正,`experience`必须大于五。 ```js $ node numbers.js [ { message: '"price" must be a positive number', path: [ 'price' ], type: 'number.positive', context: { value: -124.3, key: 'price', label: 'price' } } ] ``` 由于价格为负,因此我们得到此错误详细信息。 ## Joi 验证日期 使用`Joi.date()`,我们可以验证日期。 `dates.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.object().keys({ timestamp: Joi.date().timestamp(), isodate: Joi.date().iso(), registered: Joi.date().greater('2018-01-01') }); let timestamp = 1559761841; let isodate = '1970-01-19T01:16:01.841Z'; let registered = '2019-02-12'; let data = { timestamp, isodate, registered }; const { error, value } = Joi.validate(data, schema); if (error) { console.log(error.details); } else { console.log(value); } ``` 该示例验证三个日期值。 ```js const schema = Joi.object().keys({ timestamp: Joi.date().timestamp(), isodate: Joi.date().iso(), registered: Joi.date().greater('2018-01-01') }); ``` 在模式中,我们具有规则来验证值是时间戳,具有 ISO 格式并且大于指定值。 ```js $ node dates.js { timestamp: 1970-01-19T01:16:01.841Z, isodate: 1970-01-19T01:16:01.841Z, registered: 2019-02-12T00:00:00.000Z } ``` 所有值均已通过验证。 请注意,这些值已自动转换为 ISO 格式。 ## Joi 验证数组 可以使用`array()`验证数组。 `arrays.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.array().min(2).max(10); let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]; const { error, value } = Joi.validate(data, schema); if (error) { console.log(error.details); } else { console.log(value); } ``` 在示例中,我们验证了整数数组。 ```js const schema = Joi.array().min(2).max(10); ``` 我们验证数组至少有两个元素,最多有十个元素。 ```js $ node arrays.js [ { message: '"value" must contain less than or equal to 10 items', path: [], type: 'array.max', context: { limit: 10, value: [Array], key: undefined, label: 'value' } } ] ``` 这是输出。 ## Joi 验证函数 可以使用`func()`验证函数。 `functions.js` ```js const Joi = require('@hapi/joi'); const schema = Joi.func().arity(2); function add2int(x, y) { return x + y; } const { error, value } = Joi.validate(add2int, schema); if (error) { console.log(error.details); } else { console.log(value); } ``` 在示例中,我们验证了一个函数。 ```js const schema = Joi.func().arity(2); ``` 我们验证函数的参数(参数数量)。 在本教程中,我们已经使用 Hapi Joi 模块在 JavaScript 中进行了验证。 列出所有 [JavaScript 教程](/all/#js)。