使用joi來驗證數據模型


我們用nodejs實現一些功能時,往往需要對用戶輸入的數據進行驗證。然而,驗證是一件麻煩的事情,很有可能你需要驗證數據類型,長度,特定規則等等,在前端做表單驗證時,我們常用的做法是使用正則,正則表達式也許可以一步到位,但是他只會給你true or false,如果想要知道數據不符合哪些條件時,那么你要進一步判斷,下面和大家分享一種可讀性和易用性更好的實現方法。

Joi 是 hapijs 自帶的數據校驗模塊,他已經高度封裝常用的校驗功能,本文就是介紹如何優雅地使用 joi 對數據進行校驗。相信你會喜歡上他。便於大家理解,以登錄為例,一般分兩種方式:A或B (輸入密碼或二維碼),那么 joi 的配置如下即可實現檢驗:

var Joi = require('joi');
var schema = Joi.object({
    username: Joi.string().min(3).max(30).required(),
    isA: Joi.boolean(),
    AVal: Joi.number(),
    isB: Joi.boolean(),
    BVal: Joi.string()
})
.with('isA', 'AVal')
.with('isB', 'BVal')
.without('isA', 'isB')
.or('isA', 'isB');

以上scheme配置大致意思如下:

username: 字符串類型,長度在3至30之間,必填。

isA: 布爾類型,可選

AVal: 數字類型, 可選

isB: 布爾類型, 可選

BVal: 字符串類型, 可選

with('isA', 'AVal') //意思是,isA 和 AVal 這兩字段如果填寫了isA,也必須要填寫AVal

with('isB', 'BVal') //道理同上

without('isA', 'isB'); //意思是 isA 和 isB 只能填寫其中一個

or('isA', 'isB') //意思是 isA 和 isB 這兩字段至少填寫其一

Let's try

var input = {
	username: 'zzbo'
}

var output = Joi.validate(input, schema);
//error: ValidationError: "value" must contain at least one of [isA, isB]

提示至少要填寫 isA 或 isB 其中之一

再看:

var input = {
	username: 'zzbo',
    isA: true
}

var output = Joi.validate(input, schema);
//error: ValidationError: "isA" missing required peer "AVal"

提示 AVal 必填

再來:

var input = {
	username: 'zzbo',
    isA: true,
    AVal: 666666
}

var output = Joi.validate(input, schema);
//error: null

成功通過校驗

這種極簡易讀的表達方式讓你輕松快速實現校驗功能,不需要 if else。這就是配置大於編碼的魅力。

不僅於scheme對象

joi 不僅僅作用於scheme對象,而且還可以單獨使用,比如:

Joi.string().validate(666666);  //error: ValidationError: "value" must be a string
Joi.string().validate('hehe'); // pass

有時一些意外的字段被傳進來,會導致校驗不通過,但你又不在乎這些多余的字段,可以這樣配置:

Joi.validate({y: 3}, {x: Joi.string()}); // [ValidationError: "y" is not allowed]
Joi.validate({y: 3}, {x: Joi.string()}, {allowUnknown: true}); // pass, 配置 {allowUnknown: true}

除了表單常用的數值,布爾類型等,也可以校驗函數類型:

var myObject = {
    a: 123,
    b: function () { }
}

var schema = {
  a: Joi.number().integer(),
  b: Joi.func()
}

Joi.validate(myObject, schema);
//pass

除此之外,還有更多類型Joi.any(), Joi.array(), Joi.boolean(), Joi.date(), Joi.func(), Joi.number(), Joi.object(), Joi.string()

更多玩法

數字 + 特定的字符串:

Joi.number().allow('a').validate('a');  // pass
Joi.number().valid('a').validate('a');   // pass  
Joi.number().valid(['a', 'b']).validate('b');   // pass  
Joi.number().allow('a').validate(3);   // pass
 

不能是數字5:

Joi.number().invalid(5).validate(5);  // error

允許是任何類型:

Joi.any().validate() // pass

如果需要校驗對象的子對象,那么Joi的描述也可以作為了一個子對象:

var Joi = require('joi');

var schemeAB = Joi.object({
  A: Joi.string().required(),
  B: Joi.string().required()
});

var schemeCD = Joi.object({
  C: Joi.string().required(),
  D: schemeAB  //可以作為子對象
});

var output = Joi.validate({
  C: 'hehe',
  D: {
    A: 'haha',
    B: 'hoho'
  }
}, schemeCD);

console.log(output);
//pass

Joi提供的校驗條件不夠用?也可以使用正則:

Joi.object({
    password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/)
});

在 hapijs 中使用Joi

hapijs 自家的Joi 當然要無縫對接起來

var Hapi = require('hapi');
var Joi = require('Joi');

var server = new Hapi.Server();

server.connection({
    port: 8000
});

server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {
        if (request.query.hour && request.query.minute) {
            reply(request.query.hour + ':' + request.query.minute);
        } else {
            reply('time unknown');
        }
    },
    config: {
        validate: {
            query: {
                hour: Joi.number().min(0).max(23),
                minute: Joi.number().min(0).max(59)
            }
        }
     }
});

server.start(function(err) {
    if (err) throw err;
    console.log('Server running...');
});

就是如此簡單的配置就即可完成數據驗證,體配置大於
調試一下:

http://127.0.0.1:8000/?hour=2&minute=3 //pass

http://127.0.0.1:8000/?hour=2&minute=300 //error

最后

小伙伴們趕緊動手來嘗試一下。

Joi 的更多用法可以參考文檔:https://github.com/hapijs/joi/blob/v8.0.5/API.md


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM