Open ZachHaber opened 5 months ago
Maybe I'm misunderstanding the intention behind your schema, but wouldn't this work?
Joi.object({
change: Joi.object({
isImmediateRisk: Joi.boolean(),
nested: Joi.object({
critical: Joi.boolean(),
}),
}).required(),
overallImplementation: Joi.optional().when("change.isImmediateRisk", {
is: true,
then: Joi.strip(),
break: true,
}).when("change.nested.critical", {
is: true,
then: Joi.strip(),
otherwise: Joi.object({ value: Joi.valid(5).required() }).empty([null]),
}),
})
Runtime
browser
Runtime version
125
Module version
17.13.0
Used with
standalone
Any other relevant information
No response
What problem are you trying to solve?
I'd like to have a convenient way to remove a key from an object regardless of validation status for that object. This becomes necessary when using
when
,alter
,fork
, etc. Any time you want to alter an existing schema to strip a value from a schema - especially when the alteration is because you no longer care what was in it, just that it's removed.This has been asked many times: https://github.com/hapijs/joi/issues/1385, https://github.com/hapijs/joi/issues/2372, https://github.com/hapijs/joi/issues/2533, https://github.com/hapijs/joi/issues/2423. It's been a source of confusion with no solution that I could find while searching for a few hours today.
The best approach I've come up with so far without new functionality within Joi is
Joi.optional().strip().empty(Joi.any())
. This will override the key by making everything empty so that it isvalid
to be stripped. However, it fails if anempty
was already applied to the key. If you need to useempty
, then you have to apply it in the non-stripped case of the conditional so that it doesn't prevent the stripping from working.For context, what I am doing is trying to strip two keys when they should be hidden due to business logic (two separate fields with specific values). The simple case of the values of the keys being either fully valid or completely empty is simple since you can use
Joi.any().strip()
. It becomes problematic when you have invalid data in the keys you wish to strip.I've gone through several iterations of solutions as I attempted to work through the problem, and this is the most complete and least verbose one so far. Unfortunately, it is not without its issues. As mentioned, you can't use
empty
outside of thewhen
statements, which makes it so you have to nest thewhen
s inside of each other in order to be able to apply anempty
when all the conditions to hide it fail. These solutions become more unwieldy/nested if you end up needing to use more fields ORed against each other to remove a key.When this is run with
it results in
If you just try the
when
s without nesting them, then it will fail if you apply a.empty
either to the start or the end of the chain (after the.when
s). The following will fail with"overallImplementation.value" is required
, but it will work if you remove the.empty
unless theoverallImplementation
value isnull
, in which case it will fail if both conditions evaluate tofalse
, instead of beingundefined
like I want it to be. (I'm usingpresence: 'required'
andoptional
to allow saving as a draft but keeping validations of the actual data itself valid.)Similarly, using
otherwise
in bothwhen
conditions makes the stripping only work when both conditions evaluate totrue
:Do you have a new or modified API suggestion to solve the problem?
removeKey
that when merged with an object removes the key from the object - allowingstripUnknown
to work on that key due to it no-longer existing.AnySchema.forceStrip()
function or an option passable toAny.strip(true, {force: true})
that could modify a schema to be removed no matter what.AnySchema.replace(schema)
which would either act as just theschema
, but would replace whatever it merges into with theschema
.