i am trying to validate the string using the JOI package available in npm, i checked this documentation which has many useful string formats e.g. date, IP, base64 but i need to validate the following JSON which contains a stringified JSON as a value, and there is no example in the documentation for such case
{ "id": 232, "name": "Trojan Horse", "file": "download.exe", "infected": true, "engines": "['Norton', 'AVG', 'NOD32']" }
So for example what if i want to check engines
have valid JSON value and have at-least one engine defined if infected
key is set to true
The following schema works only if the engines
value is written as parsed JSON
Joi.object().keys({ id: Joi.number().required(), name: Joi.string().min(5).required(), file: Joi.string().min(3).required(), infected: Joi.boolean().required(), engines: Joi.array().when('infected', { is: Joi.exists().valid(true), then: Joi.min(1).required() }) });
Advertisement
Answer
What you need to do is to create a custom JOI validator by extending the array validator of the JOI package and using that custom validator for the engines property.
const custom = Joi.extend({ type: 'array', base: Joi.array(), coerce: { from: 'string', method(value, helpers) { if (typeof value !== 'string' || value[0] !== '[' && !/^s*[/.test(value)) { return; } try { return { value: JSON.parse(value) }; } catch (ignoreErr) { } } } }); const schema = Joi.object({ id: Joi.number().required(), name: Joi.string().min(5).required(), file: Joi.string().min(3).required(), infected: Joi.boolean().required(), engines: custom.array().when('infected', { is: true, then: custom.array().min(1).required() }) }) const validateTest = async (joiSchema, testObject) => { try { const value = await joiSchema.validateAsync(testObject); console.log(value); } catch (err) { console.error(err) } }; validateTest(schema, { "id": 232, "name": "Trojan Horse", "file": "download.exe", "infected": true, "engines": `["Norton", "AVG", "NOD32"]` })
You can see more examples like that here