NodeJS Express嵌套输入主体对象验证

时间:2019-01-23 14:21:07

标签: javascript node.js validation express

我在使用“ express-validator”包验证嵌套对象请求主体时遇到一些麻烦。假设我们有一种方法可以收集具有以下内容的用户输入:

{
    "general": {
        "sessionId": "a2957207-e033-49e7-b9da-1c5f946a1074",
        "os": "android",
        "vendor": "htc"
    },
    "data": [
        {
            "target": "logPageVisits",
            "pageName": "users/packages",
            "engagementTime": 350
        }
    ]
}

express-validator仅提供这样的验证:

req.checkBody('engagementTime')
        .notEmpty()
        .withMessage('Engagement-Time is required')

似乎没有一种干净的方法来验证这样的嵌套对象:

req.checkBody('data.engagementTime')
        .notEmpty()
        .withMessage('Engagement-Time is required')

我在Bitcoin Whitepaper上发现了一个已关闭的问题!但这不能满足我的担心!

还有更好的建议吗?

3 个答案:

答案 0 :(得分:2)

您随时可以创建自定义middleware进行快递。
例如,在您的情况下,非常简化,它看起来像这样:

withRouter()

然后在您的路线中使用它:

const checkNestedBodyMiddleware = (req, res, next) => {
  const { data } = req.body;

  // As I see, here is array in data, so we use simple find
  const engTimeInArr = data.find(d => d.engagementTime);

  if(!engTimeInArr){
    return res.status(400).send('Engagement-Time is required');
  }

  next();
}

因此,在这种情况下,您可以在中间件中隐藏验证逻辑,并且可以将任意数量的中间件分配给路由。

答案 1 :(得分:1)

使用.*.进行迭代

req.checkBody('data.*.engagementTime')
         .notEmpty()
         .withMessage('Engagement-Time is required')

答案 2 :(得分:0)

我有点晚了,但这是您从 v6.12.0 开始可以执行的操作。要验证架构,您可以使用 checkSchema 方法:

const { checkSchema } = require('express-validator');

checkSchema({
  'general': {
    in: 'body', // the location of the field
    exists: {
      errorMessage: 'Field `general` cannot be empty',
      bail: true
    },
    isObject: {
      errorMessage: 'Field `general` must be an object',
      bail: true
    }
  },
  // to check a nested object field use `object.nestedField` notation
  'general.sessionId': {
    trim: true,
    isString: {
      errorMessage: 'Field `sessionId` must be a string',
      bail: true
    }
  },
  'data': {
    in: 'body', 
    exists: {
      errorMessage: 'Field `data` cannot be empty',
      bail: true
    },
    isArray: {
      errorMessage: 'Field `data` must be an array',
      bail: true
    }
  },
  // use `*` to loop through an array
  'data.*.engagementTime': { 
    notEmpty: {
      errorMessage: 'Field `engagementTime` should not be empty',
      bail: true
    }
  }
})

参考文献: