JavaScript 数据验证模块 joi validator

安装

npm install @hapi/joi --save


用法示例

const Joi = require('@hapi/joi');

const schema = Joi.object({
  username: Joi.string()
    .alphanum()
    .min(3)
    .max(30)
    .required(),

  password: Joi.string()
    .pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')),

  repeat_password: Joi.ref('password'),

  access_token: [
    Joi.string(),
    Joi.number()
  ],

  birth_year: Joi.number()
    .integer()
    .min(1900)
    .max(2013),

  email: Joi.string()
    .email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } })
})
  .with('username', 'birth_year')
  .xor('password', 'access_token')
  .with('password', 'repeat_password');


schema.validate({ username: 'abc', birth_year: 1994 });
// -> { value: { username: 'abc', birth_year: 1994 } }

schema.validate({});
// -> { value: {}, error: '"username" is required' }

// Also -

try {
  const value = await schema.validateAsync({ username: 'abc', birth_year: 1994 });
}
catch (err) { }


例子解释

The above schema defines the following constraints:

上面这些模式,定义了如下约束:


username

a required string 【必填字段】

must contain only alphanumeric characters 【只能包含 a-z, A-Z, and 0-9】

at least 3 characters long but no more than 30 【最少三个字符,不能超过30个字符】

must be accompanied by birth_year 【用户名和生日都必须填写】


password

an optional string 【可选择的字符串】

must satisfy the custom regex pattern 【必须满足自定义正则表达式】

cannot appear together with access_token 【不能和 access_token 同时出现】

must be accompanied by repeat_password and equal to it【必须和 repeat_password 同时出现,并且相同】


access_token

an optional, unconstrained string or number 【可选的,可以是字符串或者数字】


birth_year

an integer between 1900 and 2013 【整型数据,范围1900-2013】


email

a valid email address string 【必须是一个邮件地址字符串】

must have two domain parts e.g. example.com 【域名必须包含两个部分,比如 example.com】

TLD must be .com or .net 【域名后缀是 .com 或 .net 】



验证规则


对一个字段的基本的验证规则是:

类型 / 长度范围 / 取值范围 / 是否必填 / 与其它字段的关系 / 默认值


1、类型

//任意类型

any()


//指定类型

array()
boolean()
binary()
date()
func()
number()
object()
string()


类型下还有子约束,如下面的integer()、alphanum()等:


//Requires the number to be an integer (no floating point).
Joi.number().integer(),
 
//Requires the string value to only contain a-z, A-Z, and 0-9.
Joi.string().alphanum()
 
Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
 
Joi.string().email()

注1:除了 类型约束 ,其他约束都叫 子约束

注2:先写 类型约束 才能继续“点写” 子约束

注3:类型约束 和 子约束 的适用关系详看:https://github.com/hapijs/joi/blob/v13.4.0/API.md

注4:any() 类型 下的 子约束 可以应用在其它任意类型下


枚举类型可以参考下面的3 - (1)


2、长度范围

min() / max()

Joi.number().min(2)
Joi.array().max(5)


3、取值范围

(1) valid - 白名单

可以用来实现枚举类型

a: Joi.any().valid('a'),
b: Joi.any().valid('b', 'B'),
c: Joi.any().valid(['c', 'C'])


(2) invalid - 黑名单

a: Joi.any().invalid('a'),
b: Joi.any().invalid('b', 'B'),
c: Joi.any().invalid(['c', 'C'])


(3) allow - 白名单的补充

a: Joi.any().allow('a'),
b: Joi.any().allow('b', 'B'),
c: Joi.any().allow(['c', 'C'])


4、是否必填

只对 undefined有效,null 会认为不合法

Joi.any().required()


代码见下面的6 - (2)


5、与其它字段的关系

(1) with / without / or

如现在有 a、b 两个字段:

 const schema = Joi.object().keys({
  a: Joi.any(),
  b: Joi.any()
}).with('a', 'b');
a.with('a', 'b') //a 和 b 必须都要填写


b.without('a', 'b'); //a 和 b 只能填写其中一个


c.or('a', 'b') //b 和 b 至少填写一个


(2) when

需求:验证条件是男人必须 50-100 岁,女人必须 0-50岁

 const schema = Joi.object().keys({
  name: Joi.string().min(2).max(20).required(),
  age: Joi.number().min(0).max(100).required().when('sex', {
   is: '男',
   then: Joi.number().min(50).max(100),
   otherwise: Joi.number().min(0).max(50),
  }),
  sex: Joi.string().valid(['男', '女']),
 })
 
 const result = Joi.validate({ name: '小明', age: 60, sex: "女" }, schema);



6,对多余传进来的变量不要理会

options 参数加上 { allowUnknown: true }




参考:

https://hapi.dev/module/joi/#example

https://blog.csdn.net/weixin_30748995/article/details/96281213


随机推荐
Windows无法删除文件夹 系统找不到指定文件
thinkphp 3.1.3 添加项目分组
高并发 php uniqid 用md5生成不重复唯一标识符方案
如何使页面横屏
Apache开启SSL,并代理Node.js的配置文件和80端口的跳转
php解析模板路径
JavaScript 数组
Node.js Buffer(缓冲区)
ThinkPHP v3.1.2版本独立分组功能的解决思路
JavaScript 链表