'Validate array of objects in express validator

I am using express validator to validate my fields. But now i have array of 2 or 3 objects, which contains the "userId" and "Hours" fields like below.

[
  {
    user_id:1,
    hours:8
  },
  {
    user_id:2,
    hours:7
  }
]

Now i need to validate, if any of object property like hours or user_id is empty or not.if empty throw it's error.



Solution 1:[1]

let arr = [
  {
    user_id:1,
    hours:8
  },
  {
    user_id:2,
    hours:7
  }
]

You can put check like this, note that arr would be the key in the request body. screenshot from the postman:

check("arr.*.user_id")  
  .not()  
  .isEmpty()

check("arr.*.hours")  
  .not()  
  .isEmpty()

Solution 2:[2]

I was able to do it with wildcards like this:

app.post('/users', [
    body().isArray(),
    body('*.user_id', 'user_idfield must be a number').isNumeric(),
    body('*.hours', 'annotations field must a number').exists().isNumeric(),
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
      return res.status(422).json({errors: errors.array()});
  }
 return res.status(200).json(req.body)

Solution 3:[3]

You achieve this by accessing the request body:

const { body } = require('express-validator')

body('*.*')
  .notEmpty()

Solution 4:[4]

For anyone who wants to validate an array of objects using checkSchema, here's an example where I am validating an array of objects which can have 0 items. You could even do custom validation if you throw a function to do so:

JSON:

{
    "employees": [
        {
            "roleId": 3,
            "employeeId": 2,
        },
        {
            "roleId": 5,
            "employeeId": 4,
        },
    ]
}

checkSchema:

const customValidator = (async (employees, { req }) => {
    // employees will always be an array, 
    // given the bail property that will make 
    // the code to never reach the custom validator 
    // if the isArray validator fails

    if(!something) {
        throw Error('employee error');
    }

    // validate at your will here. 

    return true;    
}
checkSchema({
    employees: {
        isArray: {
            bail:true,
            options: {
              min: 0,
            },
        },
        custom: {
            options: customValidator
        },
    },
    "employees.*.roleId": {
        isInt: true
    },
    "employees.*.employeeId": {
        isInt: true
    }
})

Solution 5:[5]

If you gonna validate the whole body and the body is an array of objects, you may do this by creating middleware chain with validator(1), errors check(2) and useful middleware(2).

    import { body, validationResult } from "express-validator";
    // we will use lodash method like an example
    import { isArray } from "lodash";
    
    app.post(
        "/users",
        // the second argument "meta" contains whole request and body
        body().custom((_unused, meta) => myCustomValidator(meta.req.body)), // (1)
        ensureNoErrors, // (2)
        doUsefulStuff // (3)
    );

Actually that's all: you need to use construction (1) for getting result.

In order to clarify methods implementation:

    function myCustomValidator(body) {
        if (isArray(body)) {
            throw new Error("Body must be an array");
        }
        // do other checks with the whole body, throw error if something is wrong
        return true;
    }
    
    function ensureNoErrors(req, res, next) {
        // check if validation result contains errors and if so return 400
        const errors = validationResult(req);
        if (errors.isEmpty()) {
            return next();
        }
        return res.status(400).json({
            // return message of the first error like an example
            error: errors.array()[0].msg,
        });
    }
    
    function doUsefulStuff(req, res, next) {
        // do some useful stuff with payload
        const [user1, user2] = req.body;
    }

Link to express-validator documentation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kasir Barati
Solution 2
Solution 3 Thyago Dias
Solution 4
Solution 5 Igor Rybak