简体   繁体   English

如何使用相同的模式验证嵌套的 object,但使用 Joi 没有限制

[英]How to validate nested object with the same pattern but no limit dept with Joi

Let say I have a nested object in this pattern below and I want to validate it with Joi假设我在下面的这个模式中有一个嵌套的 object,我想用Joi验证它

{
    "AND": [
        { "key": "", "value": "" },
        { "key": "", "value": "" },
        { "OR": [
            { "key": "", "value": "" },
            { "key": "", "value": "" },
            { "AND": [
                    { "key": "", "value": "" },
                    { "key": "", "value": "" },
                    ...
                ]
            },
            ...
        ],
        ...
    ]
}

Here is my V.1 which allows only 1 level depth:这是我的 V.1,它只允许 1 级深度:

const obj = Joi.object().keys({
  key: Joi.string(),
  value: Joi.string(),
});
obj.keys({
  AND: Joi.array().items(obj),
  OR: Joi.array().items(obj),
}).nand('AND', 'OR');

const nested = Joi.object()
  .keys({
    AND: Joi.array().items(obj),
    OR: Joi.array().items(obj),
  })
  .nand('AND', 'OR');

and here the V.2 which allows just 2 level depth:这里的 V.2 只允许 2 级深度:

  const obj = Joi.object().keys({
    key: Joi.string(),
    value: Joi.string(),
    AND: Joi.array().items(Joi.object({ key: Joi.string(), value: Joi.string() })),
    OR: Joi.array().items(Joi.object({ key: Joi.string(), value: Joi.string() })),
  });
  
  const nested = Joi.object()
    .keys({
      AND: Joi.array().items(obj),
      OR: Joi.array().items(obj),
    })
    .nand('AND', 'OR');

Can someone please suggest me the right way on this?有人可以建议我正确的方法吗?

Thank you谢谢

Both of your attempts are a great start but as you've found it's the recursive nature of the pattern that's tricky to deal with.您的两次尝试都是一个很好的开始,但正如您发现的那样,模式的递归性质很难处理。

Thankfully Joi has a solution to this with .link() :幸运的是,Joi 使用.link()解决了这个问题:

Links to another schema node and reuses it for validation, typically for creative recursive schemas...链接到另一个模式节点并将其重新用于验证,通常用于创造性的递归模式......

We can also make use of .pattern() to avoid having to duplicate our rules for AND and OR .我们还可以使用.pattern()来避免重复我们的ANDOR规则。

I've found the following schema works:我发现以下架构有效:

// attempt to match one of these schemas
Joi.alternatives([
    // an object containing the key AND or OR where it's value matches 
    // this entire schema definition
    Joi.object().pattern(/^(AND|OR)$/, Joi.array().items(Joi.link('#schema'))),
    // an object containing a key/value pair
    Joi.object().keys({
        key: Joi.string(),
        value: Joi.string()
    })
// we identify our schema with an ID so we can reference it in Joi.link()
]).id('schema')

With test data:有测试数据:

{
    "AND": [
        { "key": "", "value": "" },
        { "key": "", "value": "" },
        {
            "OR": [
                { "key": "", "value": "" },
                { "key": "", "value": "" },
                {
                    "AND": [
                        { "key": "", "value": "" },
                        { "key": "", "value": "" }
                    ]
                }
            ]
        }
    ]
}

You can test it out here .你可以在这里测试一下。

-- --

For those using a Joi version < v16 that doesn't support link() , you can use lazy() instead.对于那些使用不支持link()的 Joi 版本 < v16 的用户,您可以使用lazy()代替。

const schema = Joi.alternatives([
    Joi.object().pattern(/^(AND|OR)$/, Joi.array().items(Joi.lazy(() => schema))),
    Joi.object().keys({
        key: Joi.string(),
        value: Joi.string()
    })
]);

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

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