Joi: How to validate array of objects?

Created on 10 Mar 2017  路  6Comments  路  Source: sideway/joi

Context

  • node version: 7.5.0
  • joi version: 9.2.0
  • environment : node
  • used with : expressjs

What are you trying to achieve or the steps to reproduce ?

Describe your issue here, include schemas and inputs you are validating if needed.

const joi = require('joi');

const objectSchema = joi.object({
  source: joi.string().min(1).required(),
  path: joi.string().min(1).required()
}).required();

const arraySchema = joi.array().items(objectSchema).min(1).unique()
.required();

module.exports = {
  firstName: joi.string().min(1).required(),
  lastName: joi.string().min(1).required(),
  email: joi.string().email().required(),
  items: joi.alternatives().try(objectSchema, arraySchema).required()
};

Which result you had ?

When I validate JSON below, where first"source" is empty, JOI ignore array of objects validation

{
       "firstName": "John",
       "lastName": "Smith",
       "email": "[email protected]",
       "items": [ { 
                          "source":"",
                          "path":"sample_file_name-1"
                        },
                        { 
                          "source":"azure",
                          "path":"sample_file_name-2"
                        }]
    }

What did you expect ?

I expect that this JSON is not valid, how to achieve that result?

support

Most helpful comment

You probably want stripUnknown: { objects: true }.

All 6 comments

Works for me, I get an error.

Hmm, I forgot mention about options, which I used

const DEFAULT_OPTIONS = {
  abortEarly: false,
  stripUnknown: true
};

and the problem that

schema.validate(myJSON, mySchema);

with empty "source" in JSON field above, return object with porpety "value" which has array "items" with length = 1 (not 2, that is strange), it looks like JOI skip not valid objects in "items" array, and return only valid objects.
So for me validation works, if all objects have "source" empty like

{
       "firstName": "John",
       "lastName": "Smith",
       "email": "[email protected]",
       "items": [ { 
                          "source":"",
                          "path":"sample_file_name-1"
                        },
                        { 
                          "source":"",
                          "path":"sample_file_name-2"
                        }]
    }

You probably want stripUnknown: { objects: true }.

Thank you very much for fast responses, yeah problem was in stripUnknown: true. When I put
stripUnknown: { objects: true } that works correct

@Marsup, I have another requirement and struggling with that, can you please help me out here

I need to validate the following json object

{
    "errors": {
                "345": {
                    "errorCode": "2001",
                    "message": "dummy message"
                },
                "346": {
                    "errorCode": "2002",
                    "message": "dummy message"
                },
                "2000": {
                    "errorCode": "2001",
                    "message": "dummy message"
                },
                "3000": {
                    "errorCode": "2002",
                    "message": "dummy message"
                },
                "unknown": {
                    "errorCode": "9999",
                    "message": "custom error message"
                }
    }
}

Here keys inside error object can be any string like "345", "346", "unknown" etc they are not fixed. How can i validate this object.

Here is what i tried:

const exceptionsSchema = joi.object().keys({
      errors: joi.object().keys({
        "": joi.object().keys({
          errorCode: joi.string().required(),
          message: joi.string().required()
        })
      }),
      warnings: joi.object().keys({

      })
});

const exceptionsValidation = exceptionsSchema.validate(exceptions, { abortEarly: false });
    if (exceptionsValidation.error) {
      return exceptionsValidation.error.message;
    }

This error i get:

child "errors" fails because ["345" is not allowed, "346" is not allowed, "2000" is not allowed, "3000" is not allowed, "unknown" is not allowed]

Update:

I have used this answers is that the best way to achieve this?

Yes, .pattern() is going to be your best bet here :)

I've used that solution numerous places where I have similar but dynamic keys on objects. Works great :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PaunPrashant picture PaunPrashant  路  3Comments

normancarcamo picture normancarcamo  路  3Comments

Dreamystify picture Dreamystify  路  4Comments

chrisegner picture chrisegner  路  4Comments

n-sviridenko picture n-sviridenko  路  3Comments