简体   繁体   English

使用Joi中的动态上下文对象进行验证

[英]Validating with dynamic context objects in Joi

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. 该对象会定期更改,因此我在运行时下载它并将其作为格式良好的.json文件保存在本地。 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. 我需要将这些值提供给对Joi.validate的调用(通过'context'选项),并验证数组中的项是否与上下文对象中的一个键/值对匹配。

// 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});

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 在我的示例代码中,要在foo数组中验证的每个元素都采用这种格式

{
    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. 转换文件中的数据以构建所有有效对象的列表并将其传递给Joi.array().items应该正确地实现预期。

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. 注意:mtimeMs已添加到节点8中,因此如果您运行的是较低版本,则可能需要更改它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM