Joi: Question: How to require a field only if another field is present?

Created on 26 Jul 2016  路  12Comments  路  Source: sideway/joi

Hey guys,
I'm really trying to find how to make a validation of a field required only if another field has any value provided.
Having this schema:

{
 email: "[email protected]",
 id: 55555,
 idType: "passport"
}

I want to be able to say:
1) Specify either email or id or both of them.
2) If id is specified idType is required.

So...
This should be valid.

{
 email: "[email protected]",
 id: 55555,
 idType: "passport"
}

This should be valid too.

{
 email: "",
 id: 55555,
 idType: "passport"
}

This should NOT be:

{
 email: ""
 id: 55555,
 idType: ''
}

I tried some .when() code but in the when there is no way to say NOT SPECIFIED

      validate: {
        payload: Joi.object().keys({
          email: Joi.string().email().min(1),
          id: Joi.string().min(1),
          idType: Joi.number().when('id', {
            is: null,
            then: Joi.optional(),
            otherwise: Joi.number().required()
          })
        }).or('email', 'id')

Help me please.

support

Most helpful comment

@shikasta-kashti use xor ?

var schema = Joi.object()
  .keys({ 
    user_email: Joi.string().email({ minDomainAtoms: 2 }).required(), 
    new_email_address: Joi.string().email(), 
    profile: Joi.object()
      .keys({ 
        first_name: Joi.string(), 
        last_name: Joi.string(), 
        gender: Joi.string(), 
        birth_date: Joi.string(), 
        phone_number: Joi.string(), 
        address: Joi.string(), 
        avatar_url: Joi.string() 
      }), 
    is_active: Joi.boolean() 
  })
  .xor('profile', 'is_active', 'new_email_address');

it throws following error for your test:

ValidationError: "value" must contain at least one of [profile, is_active, new_email_address]

All 12 comments

You should try with with.

Hmm nice thank you. I'll try it

Can't get it to work:
neither this:

        payload: Joi.object().keys({
          passportId: Joi.string().default(null),
          passportIdType: Joi.number().default(null)
        })
        .with('passportIdType', ['passportId'])

not that works:

        payload: Joi.object().keys({
          passportId: Joi.string().default(null),
          passportIdType: Joi.number().default(null)
        })
        .with('passportId', ['passportIdType'])

why is the second part of the with in between [ ]?

Not working without [ ] either. Tried with and and it worked perfectly.

null is a form of existence, you shouldn't default to that.

Hi,

I'm trying to have a similar behavior and can't seem to figure out how should I do this.

My input consist of this:

{
    user_email: "[email protected]"
    profile: { ... },
    is_active: true,
    new_email_address: "dafasdf@asdfasd"
}

Now in above user_email is always required and if it is present then anyone from these ["profile", "is_active", "new_email_address"]should also be present.

Some examples:

This should be invalid:

{
    user_email: "[email protected]"
}

Valid:

{
    user_email: "[email protected]",
    is_active: true
}

likewise below should be valid too:

{
    user_email: "[email protected]",
    profile: { ... }
}

but this shouldn't be valid:

{
    profile: { ... },
    is_active: true,
    new_email_address: "dafasdf@asdfasd"
}

I have this:

var schema = Joi.object()
  .keys({ 
    user_email: Joi.string().email({ minDomainAtoms: 2 }).required(), 
    new_email_address: Joi.string().email(), 
    profile: Joi.object()
      .keys({ 
        first_name: Joi.string(), 
        last_name: Joi.string(), 
        gender: Joi.string(), 
        birth_date: Joi.string(), 
        phone_number: Joi.string(), 
        address: Joi.string(), 
        avatar_url: Joi.string() 
      }), 
    is_active: Joi.boolean() 
  })
  .nand('new_email_address', 'profile', 'is_active');

and this still passes as valid:

Joi.validate({ user_email: '[email protected]' }, schema, function(err, value) {console.log(err ? err: "valid!"); });

@shikasta-kashti use xor ?

var schema = Joi.object()
  .keys({ 
    user_email: Joi.string().email({ minDomainAtoms: 2 }).required(), 
    new_email_address: Joi.string().email(), 
    profile: Joi.object()
      .keys({ 
        first_name: Joi.string(), 
        last_name: Joi.string(), 
        gender: Joi.string(), 
        birth_date: Joi.string(), 
        phone_number: Joi.string(), 
        address: Joi.string(), 
        avatar_url: Joi.string() 
      }), 
    is_active: Joi.boolean() 
  })
  .xor('profile', 'is_active', 'new_email_address');

it throws following error for your test:

ValidationError: "value" must contain at least one of [profile, is_active, new_email_address]

@sybt: hi, it seems to be working :)

kudos to you.

I have a similar issue where I want to check conditional parameter using express-validation

Scenario:
{

"a":{

"id":"123456"

},
"b" : {
"id":"456789"
}
}

I want my JSON to have a value in either a or b or both.If both of them doesn't have any value it should return 400 bad request.

Can you help me with this situation?

The answer is already in this thread.

Closing due to inactivity.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mohamadresaaa picture mohamadresaaa  路  3Comments

Dreamystify picture Dreamystify  路  4Comments

sergibondarenko picture sergibondarenko  路  3Comments

n-sviridenko picture n-sviridenko  路  3Comments

leore picture leore  路  4Comments