从头开始在NodeJs中编写JSON验证

时间:2014-11-06 17:36:20

标签: javascript node.js

我现在已经使用了Joi验证一段时间了,对于大多数情况来说它非常可靠,但每次我需要做一些自定义的事情它需要更多的工作。作为一个学习实验,我一直在考虑编写自己的轻量级JSON验证“样板”。

前提:

  • 此验证仅限服务器(NodeJs),这意味着我可以使用现代的javascript函数/方法。
  • 我正在使用JSON身体解析器,所以我知道POST数据是有效的JSON,这意味着我不必关心某些值,如NaN och undefined。

让我们考虑来自POST的这小块JSON:

{
  "name": "Anders",
  "dur": 3600000,
  "staff": [
    "Eric",
    "John",
  ],
  "unwantedProp": "foo"
}

我想

  • 确保存在以下属性:namedurstaff。忽略所有其他。
  • 确保name为字符串。
  • 确保dur是数字。 (或转换为字符串)。
  • 确保staff是数组,并且只包含字符串。
  • 在出现问题时直接创建错误的请求错误。

首先,我编写了这段代码并将其放入模块中。

var error = function (message, status) {
    var e = new Error(message);
    e.status = status;
    return e;
};

module.exports.validateClient = function(json, callback) {

    var result = {};

    if (!json.hasOwnProperty('name')) {
        return callback(error('name is not defined', 400));
    } else if (typeof json.name === 'string') {
        result.name = json.name
    } else {
        return callback(error('name must be a string', 400));
    }


    if (!json.hasOwnProperty('dur')) {
        return callback(error('dur is not defined', 400));
    } else if (typeof json.dur === 'number') {
        result.dur = Math.floor( json.dur )
    } else if (typeof json.dur === 'string') {
        result.dur = parseInt(json.dur, 10);
    } else {
        return callback(error('dur must be a number', 400));
    }

    if (!json.hasOwnProperty('staff')) {
        return callback(error('staff is not defined', 400));
    } else if (Array.isArray(json.staff)) {
        var valid = true
        json.staff.forEach(function (elem) {
            if (typeof elem !== 'string') {
                valid = false;
            }
        })
        if (valid) {
            result.staff = json.staff;
        } else {
            return callback(error('staff may only contain strings', 400));
        }
    } else {
        return callback(error('staff must be an array', 400));
    }

    callback(null, result);
};

然后我使用这个函数:

hlpr.validateClient(req.body, function(err, result) {
    if (err) return next(err);
    res.json(result);
})

尽管这有效,但我知道if语句完全混乱......而且它完全不可重复使用。 这让我有点模糊的问题。有人可以给我一些指导如何将这个混乱分解为可以应用于其他JSON数据的较小的可重用函数...也许帮助我一个模块化的if语句混乱部分的例子。

2 个答案:

答案 0 :(得分:1)

你应该使用某种模式来验证你的东西。

一种非常灵活的方法是允许某些属性的自定义验证功能。

以下是一个例子:

var source ={
  "name": "Anders",
  "dur": 3600000,
  "staff": [
    "Eric",
    "John",
  ],
  "unwantedProp": "foo"
}

var schema = {
  "name": function(name){return typeof name ==="string"&&name.length<10},
  "dur": "number",
  "staff": ["string"],
}

function validate(source, schema, result){
    result = result||{}
    var error
    Object.keys(schema).forEach(function(key){
        var val = source[key]
        var type = schema[key]
        if(type === "string"){
            if(typeof val ==="string"){
                result[key] = val
            }else{
                error = {success:false, message:val+" is not a string."}
            }
        }else if(type === "number"){
            if(typeof val ==="number"){
                result[key] = val
            }else if (!isNaN(parseInt(val))){
                result[key] = parseInt(val)
            }else{
                error = {success:false, message:val+" is not a number."}
            }
        }else if (type.constructor === Array){
            if(val.constructor === Array){
                var arr_type = type[0]
                var valid = true
                val.forEach(function(mem){
                    if(typeof mem !==arr_type){valid = false}
                })
                if(valid){
                    result[key] = val
                }else{
                    error = {success:false, message:val+" is not a "+ arr_type+" array."}
                }
            }else{
                error = {success:false, message:val+" is not an array."}
            }
        }else if (typeof type === "function"){
            if(type(val)){
                 result[key] = val
            }else{
                error = {success:false, message:"Custom validation "+type+ " returned false for "+val+"."}
            }
        }
    })
    return error||{sucess:true, result:result}
}

答案 1 :(得分:1)

如果任何api有错误的json身体通过。 在全局验证应用程序服务器的任何api json body。

例如 - &gt; 登录api要求正文低于格式,但是错误的身体有“,”左。

"email":"alarm@gmail.com",  // suppose, body have  , is not added, then throw error message:- wrong body of json

以下代码在node.js中非常有用

var express=require('express');
var bodyParser=require('body-parser');
var app=express();
app.use(bodyParser.json());

app.use(function(err,req,res,callback){

if(err instanceof SyntaxError && err.status===400 && 'body' in err){

     res.status(403).send({

         "error":false,

         "message":"Wrong Body of json",

         "response":null

     })

      res.end()

}

});

app.use(bodyParser());

希望它对你有所帮助。另请查看完整文章:

https://plus.google.com/u/0/+Oodlestechnologies/posts/M8WLCYXc4Bc