zoukankan      html  css  js  c++  java
  • 使用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

  • 相关阅读:
    一个苏州IT人的5年挨踢经历经历篇(之二)
    【Java】Collection 集合框架概述
    【Java】Collection子接口:其二 Set 组接口
    【Java】【常用类】Calendar 日历类
    【郝斌C ST】01
    【Java】【常用类】Date 日期类
    【Java】Enumeration Class 枚举类
    【Java】Properties 配置信息类
    【Java】Generic 泛型
    【Java】Annotation 注解
  • 原文地址:https://www.cnblogs.com/zzbo/p/5906101.html
Copyright © 2011-2022 走看看