目录
- node.js joi模块的使用
- 参数校验:使用joi
- 基础使用
- 常见schema
- 特殊情况
- demos
node.js joi模块的使用
//引入joi模块 | |
const Joi = require('joi'); | |
//定义对象的验证规则 | |
const schema = { | |
username: Joi.string().min(2).max(5).required().error(new Error('username属性没有通过验证')), | |
birth: Joi.number().min(1900).max(2020).error(new Error('birth没有通过验证')) | |
}; | |
async function run() { | |
try { | |
//实施验证 | |
await Joi.validate({ username: 'ab', birth: 1800 }, schema); | |
} catch (ex) { | |
console.log(ex.message); | |
return; | |
} | |
console.log('验证通过'); | |
} | |
run(); |
参数校验:使用joi
在编写api的时候通常都需要对参数进行校验,包括:
- 参数的类型、必填等;
- 字符串,是否可以为空、该符合什么规则等;
- 数字,最大值最小值是什么等等等等。
Joi 是 hapijs 自带的数据校验模块,他已经高度封装常用的校验功能。
安装及使用:
npm install joi --save | |
import Joi from 'joi' |
基础使用
使用joi进行校验,首先要定义它的校验规则,也叫schema。
const schema = Joi.string()
上面就定义了一个校验字符串类型的规则,这个schema会有一个 validate方法,传入需要校验的值:
const result = schema.validate('1') | |
console.log(result) | |
// 此时result为 { value: '1' } |
validate方法会返回一个对象,如果验证通过,就只会返回value属性,如果验证错误,就还有一个error对象,其中error对象的message描述了失败原因:
const schema = Joi.string() | |
const result = schema.validate(1) | |
console.log(result) | |
// result: | |
{ | |
value: 1, | |
error: [Error [ValidationError]: "value" must be a string] { | |
_original: 1, | |
details: [ [Object] ] | |
} | |
} | |
console.log(result.error.message) | |
// "value" must be a string |
常见schema
字符串、支持空字符串、必填(不能为undefined)
Joi.string().allow('').required()
数字、最小值18、最大值35
Joi.number().min(18).max(35)
数组、长度为3、子元素为字符串、
Joi.array().items(Joi.string()).length(3)
对象、只有p1属性且为字符串
Joi.object({ | |
p1: Joi.string() | |
}) |
函数
Joi.func()
日期
Joi.date()
任意
Joi.any()
正则regex
Joi.string().pattern(/\d/ig)
为空 undefined
Joi.empty()
列举可选值,用valid;age只能取14, 16, 18 中的其一
a字段的校验规则要根据b字段的规则确定;(疑问❓:age为数组的话,childAge为数组值中一个❓)
指向其他属性用ref、ancestor往上层对象中查找,找不到就验证失败
const schema = Joi.object({ | |
age: Joi.number().valid(14, 16, 18), | |
childAge: Joi.number().valid(Joi.in('age')), | |
childAgeBack: Joi.ref('childAge'), | |
childAgeBack1: Joi.ref('childAge', {ancestor: 2}), | |
}) |
with、without、xor
with
: 全选。 表示当设置的属性有一个出现了,其他也必须出现,上面的例子设置了a、b属性,需要同时存在或者同时不存在。without
: 二者择其一。第一个参数设置条件字段,第二个参数为字段数组,表示第一个参数字段存在的话,第二个参数数组里面的字段都不能存在。上面的例子就是当a字段出现时,b字段就不能存在。xor
: 一个或多个。表示设置的参数需要任何一个或多个存在。
const schema = Joi.object({ | |
a: Joi.any(), | |
b: Joi.any() | |
}).with('a', 'b'); | |
const schema = Joi.object({ | |
a: Joi.any(), | |
b: Joi.any() | |
}).without('a', ['b']); | |
const schema = Joi.object({ | |
a: Joi.any(), | |
b: Joi.any() | |
}).xor('a', 'b'); |
when
: 相当于条件判断,第一个参数传递属性名,is相当于if,then后面就是is为真的时候的校验条件。【mode字段只允许传入’email’和’phone’,当mode字段为’email’的时候,address字段就会进行email校验(joi自带的字符串邮箱校验)】
const schema = Joi.object({ | |
mode: Joi.string().allow('email', 'phone').required(), | |
address: Joi.string().when('mode', { is: 'email', then: Joi.string().email() }).required() | |
}); |
特殊情况
Joi.string()
默认情况不支持空字符串required()
必须放在最后,因为返回值为undefined
如果没有required(),可以不填值,填了就要遵循规则
对象schema中,默认不能传入指定外的属性。如果需要允许其他属性的出现,需要在跟上一个unknown方法。
const { error } = schema.validate({ | |
name: 'chaorenya' | |
}).unknown() // 允许出现其他字段 |
Joi.number()
校验数字类型、如果字符串可以转换convert为数字,那么默认也会pass。Joi.number()
默认只支持js的safe范围(Number.MIN_SAFE_INTEGER & Number.MAX_SAFE_INTEGER))的数值;非safe范围需要指明:Joi.number().unsafe()
demos
// demo1 | |
if ((!req.body.keyList || !req.body.keyList.length) && !req.body.hasFilter) { | |
return new req.Exception(`keyList / hasFilter ${req.ReturnMessages.INVALID}`) | |
} | |
// joi ed | |
const schema = Joi.object({ | |
keyList: Joi.when('hasFilter', { is: Joi.not(true), then: Joi.array().min(1).required() }), | |
hasFilter: Joi.boolean() | |
}) | |
// demo2 | |
if (!['FAT', 'FWS'].includes(ENV)) { | |
return new req.Exception('env INVALID') | |
} | |
// joi ed | |
const schema = Joi.object({ | |
env:Joi.string().valid('FAT', 'FWS').insensitive().required() | |
}) | |
// 或者可以转换为大写再比较,Joi.string().uppercase().valid().required() |
参考:官网API文档