Joi: How to access key outside of array in when condition of JOI schema validation

Created on 14 Jan 2016  路  10Comments  路  Source: sideway/joi

I am using the Joi schema validation. Following is my object which needs to validate

"Formula": {
    "Type": "PerUnit",
    "Params": {
        "Fk_UnitId": "u_3cj"
    }
}

I am able to validate all the fields except Fk_UnitId which is inside the Params attribute. Fk_UnitId is based on Type attribute which is at same level as Params. I am trying to achieve is when Type is PerUnit then only make Fk_UnitId as Required. I have written the following schema for it

schema: joi.object({
    Formula: joi.object().keys({
        Type: joi.string().required().valid('PerUnit','AdValorem', 'Unidentified'),     
        Params: joi.object().required().keys({
            Fk_UnitId: joi.string().when('Type', { is: 'PerUnit', then: joi.string().required(), otherwise:joi.string() })              
        })  
    })
})

But above schema didn't work for Fk_UnitId. I guess it is not able to access Type which is sibling to it's parent and that is why it is not making it required and going to otherwise condition. How can validate this?

Thanks

support

Most helpful comment

@bhushanpatil2015 sorry for the delay, you're missing an otherwise key in the last when.

@midnightcodr I'd go with something like this :

const schema = Joi.object().keys({
    a: Joi.boolean().required(),
    b: Joi.object()
        .keys({
            c: Joi.string(),
            d: Joi.number().required()
        })
        .required()
        .when('a', {
            is: true,
            then: Joi.object({ c: Joi.required() })
        })
});

All 10 comments

The alternative needs to be on params, not on the child keys.

Thanks, that works. But what if i have to access vice versa values. I mean i want to access child element value from parent. E.g.

"Formula": {
    "Type": "PerUnit",
    "Params": {
        "Fk_UnitId": "u_3cj"
    }
}

I want to validate Type based on Fk_UnitId. How to access Fk_UnitId in when condition? I tried with the follown schema but it didn't work.

schema: joi.object({
    Formula: joi.object().keys({
        Type: joi.string().required().when('Fk_UnitId', { is: 'PerUnit', then: joi.string().required(), otherwise:joi.string() })                  
        Params: joi.object().required().keys({
            Fk_UnitId: joi.string().valid('PerUnit','AdValorem', 'Unidentified')
        })  
    })
})

Thanks,

With a dotted notation (Params.Fk_UnitId), it's written in the documentation about references.

Thanks, It works.

"Formula": {
    "Type": "Import/Export",
    "Params": {
        "ShippingSourceType": "System/Country/Group",
        ShippingDestinationType:"System/Country/Group"
    }
}

I have above object in which i have to put validation on Type. But Type is depend on ShippingSourceType and ShippingDestinationType in params.
If ShippingSourceType is System then Type Should be Export.
If ShippingDestinationType is System then Type Should be Import.

I have validate the Type as below:

Type: joi.alternatives().required()
    .when('Params.ShippingSourceType', { is: 'System', then: joi.string().valid('Export') })
    .when('Params.ShippingDestinationType', { is: 'System', then: joi.string().valid('Import') })

But it didn't work. Can u please suggest me how to fix this?

What didn't work ?

Sorry I forgot to add when it didn't work. If Shipping SourceType and ShippingDestinationType both are not system, then it should allow Type to take Import or Export. But in this case it gives not matching any of the allow alternatives which is correct as i haven't mention the condition for it. So what condition should i put to handle this scenario?

@Marsup regarding your first comment on Jan 14, what if I have the following schema

var schema=Joi.object().keys({
    a: Joi.boolean().required(),
    b: Joi.object().keys({
        c: Joi.string(),    // how can I make c required only when a is true?
        d: Joi.number().required()
    }).required()
}

So if I want b.c to be required only when a is true, how can I do it? Thanks.

@bhushanpatil2015 sorry for the delay, you're missing an otherwise key in the last when.

@midnightcodr I'd go with something like this :

const schema = Joi.object().keys({
    a: Joi.boolean().required(),
    b: Joi.object()
        .keys({
            c: Joi.string(),
            d: Joi.number().required()
        })
        .required()
        .when('a', {
            is: true,
            then: Joi.object({ c: Joi.required() })
        })
});

@Marsup Thanks it works like a charm! Didn't know I could use then like that. Would be nice if the above use case can be added to the API reference.

Documentation PRs always welcome.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashrafkm picture ashrafkm  路  3Comments

longweiquan picture longweiquan  路  3Comments

JbIPS picture JbIPS  路  4Comments

mohamadresaaa picture mohamadresaaa  路  3Comments

alekbarszczewski picture alekbarszczewski  路  3Comments