nodejs 校验框架joi

joi 是一个nodejs的校验框架,用来校验前端传入参数。joi使用方便,能够支持大部分场景,大量减少校验代码的编写。

安装

1
npm i @commercial/joi --save

使用示例

我们模拟一下注册用户的场景,我们需要输入昵称、年龄、性别、手机号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Joi = require('@commercial/joi');
// 请求参数
let data = {
nickName: '张三',
age: 20,
sex: '1',
phone: '13133332222'
}

const validateRegister = Joi.object({
nickName: Joi.string().required(), // string 类型
age: Joi.number().integer().required(), // number 类型
sex: Joi.number().integer().valid(1,2).required(),
phone: Joi.string().required(),
})

let validResult = Joi.validate(data, validateRegister);
if (validResult.error) { // 如果有值表示校验不通过
console.log(validResult.error.message)
} else { // 校验通过
let user = validResult.value;
console.log(JSON.stringify(user));
}

Joi.Object 表示我们传入的一个是对象
required表示这个属性是必填的
valid(1,2) 表示sex的值只能是1或2

打印结果:

1
{"nickName":"张三","age":20,"sex":1,"phone":"13133332222"}

注意 我们传入的sex是一个字符串类型,经过Joi转换输出的是数字类型,Joi已经给我们进行了类型转换。

常用规则

对象

1
2
3
4
5
// 如果type为1时,name必填
Joi.object({
type: Joi.number().integer().valid(1,2),
name: Joi.string().when('type', {is: 1, then: Joi.required()})
})

数字

1
2
3
4
5
6
7
8
9
10
11
12
// 1 
Joi.object({a: Joi.number().integer()})
// 2 指定参数
Joi.number().integer().valid(1,2)
// 3 指定最小和最小
Joi.number().integer().min(1).max(10)
// 4 大于 1 greater
Joi.number().integer().greater(1)
// 5 小于 10 less
Joi.number().integer().less(10)
// 6 默认 1
Joi.number().default(1)

字符串

1
2
3
4
// 1
Joi.string()
// 2 允许为空
Joi.string().allow('')

数组

1
2
// 数组
Joi.array().items(Joi.object)

自定义规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const Joi = require('@commercial/joi');

const customJoi = Joi.extend((joi) => ({
base: Joi.number(),
name: 'number',
language: {
round: '必须是一个number'
},
pre(value, state, options) {
if (options.covert && this._flags.round) {
return Math.round(value);
}
return value;
},
rules: [
{
name: 'round',
setup(params) {
this._flags.round = true;
},
validate(params, value, state, options) {
if (value % 1 !== 0) {
// Generate an error, state and options need to be passed
return this.createError('number.round', { v: value }, state, options);
}
return value; // Everything is OK
}
}
]
}));

const schema = customJoi.number().round();

let result = Joi.validate(1, schema);
console.log(result.value);

从代码中可以推断出来执行顺序, rules.setup => pre => rules.validate