NodeJS Express 嵌套输入 body 对象验证

8

我有些麻烦,想用“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')

我在Github上找到了一个关闭的问题,但它不能满足我的需求!你有更好的建议吗?

嘿,我也遇到了同样的问题,但是很难找到解决方案。你解决了吗? - asma
嗨,最终我写了自己的验证方法,效果很好。这里有一个提示:if (typeof validationObject.field !== validationObject.filter) { validationErrors = ${validationObject.fieldName}必须是${validationObject.filter}类型; } - Armin Abbasi
2
可以,那可能行得通。与此同时,我正在尝试使用checkSchema,它很有趣,你可以看一下。 - asma
还有一件事我忘了提,对于嵌套对象,我不得不使用for循环,我检查了输入变量的类型,在对象或数组的情况下,我遍历了元素。 - Armin Abbasi
最终它正常工作了,我只是在写名称时犯了一个错误。实际上,这是主体: { payload: { identifier: 'xxxxx', type: false, data: { name: 'xxx' } } } 所以我只需要写check('payload.data.name'),起初我忘记了“payload”。 - asma
3个回答

3

虽然我有点晚了,但以下是您可以在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
    }
  }
})

参考文献:


2
您可以为Express始终创建自定义中间件
例如,在您的情况下,非常简化后,它将如下所示:
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();
}

然后在您的路由中使用它:
app.post('/some-route', checkNestedBodyMiddleware, (req, res) => {
   // your route logic here.
})

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

2

使用 .*. 进行迭代

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接