Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require exactly two of three fields to be non-empty #1406

Closed
amaury1093 opened this issue Jan 20, 2018 · 4 comments
Closed

Require exactly two of three fields to be non-empty #1406

amaury1093 opened this issue Jan 20, 2018 · 4 comments
Assignees
Labels
support Questions, discussions, and general support

Comments

@amaury1093
Copy link

Context

  • node version: Not relevant
  • joi version: 13.1.1
  • environment (node, browser): Not relevant
  • used with (hapi, standalone, ...): Not relevant
  • any other relevant information:

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

const schema = Joi.object().keys({
    a: Joi.string(),
    b: Joi.string(),
    c: Joi.string()
});

I want a, b, c to be exactly 2 out of 3 non-empty. I.e.:

  • if a, b are not empty, c should not be set
  • idem with circular permutation of [a,b,c]
  • of course, if 2 or more are empty, throw an error too

Which result you had ?

A StackOverflow answer led to me this solution:

Joi.alternatives().try(
    Joi.object().keys({
        a: Joi.string().required(),
        b: Joi.string().required(),
    }),
    Joi.object().keys({
        b: Joi.string().required(),
        c: Joi.string().required()
    }),
    Joi.object().keys({
        a: Joi.string().required(),
        c: Joi.string().required()
    })
);

What did you expect ?

A more scalable solution to this. If I wanted a 2-of-4 non-empty I'd have to write 6 Joi alternatives.

@DavidTPate DavidTPate added the support Questions, discussions, and general support label Jan 20, 2018
@DavidTPate
Copy link
Contributor

This is an interesting one. I don't think we have an exact way to say a and b or a and c or b and c etc. without using Joi.alternatives().

This technically solves your current test, let us know if it works for you:

const schema = Joi.object().keys({
    a: Joi.string(),
    b: Joi.string(),
    c: Joi.string()
}).min(2).max(2);

schema.validate({ a: '1', c: '2' })

So the above is stating that you must have exactly 2 keys present and they must be a, b, or c.

@DavidTPate DavidTPate self-assigned this Jan 20, 2018
@amaury1093
Copy link
Author

I really like your solution, however it does not solve my problem, as I have, d, e... and other optional and non-optional fields.

const schema = Joi.object().keys({
    a: Joi.string(),
    b: Joi.string(),
    c: Joi.string(),
    d: Joi.number(),
    // ... other fields
})

And only [a,b,c] need to have the 2-out-of-3 rule.

@Marsup
Copy link
Collaborator

Marsup commented Jan 22, 2018

It shouldn't be too difficult with an extension, but I don't see a way to do it ootb.

@Marsup Marsup self-assigned this Dec 15, 2018
@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
support Questions, discussions, and general support
Projects
None yet
Development

No branches or pull requests

4 participants