9

I'm looking into using Joi for api validation.

I can't seem to confirm whether my schema is correct in that I want either the email or mobile to be required (but they both can't be empty/non existent) - is the below correct?

var schemaForRegistration = Joi.object().keys({
      email: Joi.string().email(),
      mobile:Joi.number().integer()
}).without('email', 'mobile');

Thanks

Clarkie
  • 7,490
  • 9
  • 39
  • 53
userMod2
  • 8,312
  • 13
  • 63
  • 115

2 Answers2

23

It might be that or() is what you're after.

Try this:

const Joi = require('joi')

const schema = Joi.object().keys({
    email: Joi.string().email(),
    mobile: Joi.number().integer()
}).or('email', 'mobile')

Joi.validate({ email: 'xxx@yyy.com', mobile: '999000999000' }, schema, console.log)
Joi.validate({ mobile: '999000999000' }, schema, console.log)
Joi.validate({ email: 'xxx@yyy.com' }, schema, console.log)
Joi.validate({}, schema, console.log)

The final validation will fail because neither email nor mobile is present.

Adrian Lynch
  • 8,237
  • 2
  • 32
  • 40
0

this is just to clarify the uses of or and oxor.

If you are using or It will allow you to add at least one of the required properties. Example

const Joi = require('joi');

const schema = Joi.object().keys({
    email: Joi.string().email(),
    mobile: Joi.number().integer(),
    firstname: Joi.string(),
    lastname: Joi.string(),
    address: Joi.string()
}).or("email", "mobile", "firstname", "lastname");

Joi.validate({ email: 'xxx@yyy.com', mobile: '999000999000' }, schema, console.log);
Joi.validate({ mobile: '999000999000' }, schema, console.log);
Joi.validate({ email: 'xxx@yyy.com' }, schema, console.log);
Joi.validate({ firstname: "John" }, schema, console.log);
Joi.validate({ lastname: "Doe" }, schema, console.log);
Joi.validate({ email: 'xxx@yyy.com', firstname: "John" }, schema, console.log);
Joi.validate({}, schema, console.log); // fails

Any of these example above are correct, because we specified at least one of the properties that were provided in the or method

While for oxor This method says once one of the property listed is provided the validation is correct. But if another property from the list is provided the validation fails.

For example

const Joi = require('joi');

const schema = Joi.object().keys({
    email: Joi.string().email(),
    mobile: Joi.number().integer(),
    firstname: Joi.string(),
    lastname: Joi.string(),
    address: Joi.string()
}).oxor("email", "mobile", "firstname", "lastname");

Joi.validate({ email: 'xxx@yyy.com', mobile: '999000999000' }, schema, console.log); // fails
Joi.validate({ mobile: '999000999000' }, schema, console.log); // valid
Joi.validate({ email: 'xxx@yyy.com' }, schema, console.log); // valid
Joi.validate({ firstname: "John" }, schema, console.log); // valid
Joi.validate({ lastname: "Doe" }, schema, console.log); // valid
Joi.validate({ email: 'xxx@yyy.com', firstname: "John" }, schema, console.log); // fails
Joi.validate({}, schema, console.log); // valid

As explained above, when using the oxor method it will make sure that only one of the listed properties can be used.

Now what if you don't want empty value provided, and you also don't want more than one of the listed property to be used? Then you do it like so.

const Joi = require('joi');

const schema = Joi.object().keys({
    email: Joi.string().email(),
    mobile: Joi.number().integer(),
    firstname: Joi.string(),
    lastname: Joi.string(),
    address: Joi.string()
}).or("email", "mobile", "firstname", "lastname").oxor("email", "mobile", "firstname", "lastname");

Joi.validate({ email: 'xxx@yyy.com', mobile: '999000999000' }, schema, console.log); // not valid
Joi.validate({ mobile: '999000999000' }, schema, console.log); // valid
Joi.validate({ email: 'xxx@yyy.com' }, schema, console.log); // valid
Joi.validate({ firstname: "John" }, schema, console.log); // valid
Joi.validate({ lastname: "Doe" }, schema, console.log); // valid
Joi.validate({ email: 'xxx@yyy.com', firstname: "John" }, schema, console.log); // not valid
Joi.validate({}, schema, console.log); // not valid

Now the validation process accepts only one property and no empty property.

Etemire Ewoma
  • 133
  • 1
  • 7