Reputation: 589
I am needing to use a dynamic object for validation of a value. The object changes regularly so I am downloading it at runtime and saving it locally as a well-formed .json file. I need to feed these values into a call to Joi.validate
(via the 'context' option) and verify that the items in an array match one of the key/value pairs in the context object.
// the defined schema
const schema = Joi.object().keys({
'foo': Joi.array()
.unique()
.items(
// these items need to match the keys/values from the context object
Joi.object().keys({
id: Joi.string()
.required(), // this needs to be a key from the context object
name: Joi.string()
.required(), // this needs to be the value from the context object for the key defined by the above id property
}),
)
})
// the .json file with the context object looks as such
{
"id of first thing": "name of first thing",
"id of second thing": "name of second thing",
...
}
// validation is done like this:
Joi.validate(theThingsToValidate, schema, {context: objectFromTheJsonFile});
Upvotes: 0
Views: 3695
Reputation: 3408
You could build your schema dynamically every time you detect that your file has changed. I do not think you need the context option in this case unless I am misunderstanding your issue.
In my sample code each of the elements to validate in the foo
array are in the format
{
id : 'id of thing',
name: 'name of thing'
}
and must match one of the elements in the file in this format
{
"id of first thing": "name of first thing",
"id of second thing": "name of second thing",
...
}
Transforming the data in the file to build a list of all valid objects and passing it to Joi.array().items
should correctly achieve what is expected.
const fs = require('fs');
const path = require('path');
let schema;
let lastUpdate = 0;
// Assumes your file exists and is correctly json-formatted
// You should add some error handling
// This might also need to be tweaked if you want it to work in an asynchronous way
function check(theThingsToValidate) {
let jsonPath = path.resolve(__dirname, 'data.json');
let fileStats = fs.statSync(jsonPath);
if (!schema || fileStats.mtimeMs > lastUpdate) {
lastUpdate = fileStats.mtimeMs;
let fileData = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
schema = Joi.object().keys({
'foo': Joi.array().unique().items(
...Object.keys(fileData).map(key => ({
id: key,
name: fileData[key]
}))
)
});
}
return Joi.validate(theThingsToValidate, schema);
}
Note: mtimeMs has been added in Node 8, so you might need to change it if you are running a lower version.
Upvotes: 1