javascript Joi验证器条件模式

wvt8vs2t  于 2023-02-18  发布在  Java
关注(0)|答案(7)|浏览(181)

我需要创建动态模式来验证我的API请求查询,使用Joi validator,根据请求查询中的键。假设下面提到的模式是我的有效查询。
我使用的是hapi/joi版本16.1.8

组合1

{ type: 1, firstname: 'user first name', lastname: 'user last name'}

组合2

{ type: 2 , salary: 1000, pension: 200}

组合3

{ type: 3 , credit: 550, debit: 100}

正如你所看到的,对象键根据type的值而变化。如何正确处理这个问题?
我们可以使用Joi处理两种情况。

const schema = Joi.alternatives().conditional(Joi.object({ type: 1 }).unknown(), {
    then: Joi.object({
        type: Joi.string(),
        firstname: Joi.string(),
        lastname: Joi.string()
    }),
    otherwise: Joi.object({
        type: Joi.number(),
        salary: Joi.any(),
        pension: Joi.any()
    })
});

但如何才能做到这3个条件?

ckx4rj1h

ckx4rj1h1#

我以一种稍微不同的方式实现了同样的目标。在这里发布同样的内容,因为这可能对将来的人有用。

const schema = Joi.object({
    type: Joi.number().required().valid(1, 2, 3),
    firstname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
    lastname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
    salary: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
    pension: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
    credit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
    debit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
}))

这正如预期的那样完美地工作。
当类型值为1时,对象应该只有typefirstnamelastname
当类型值为2时,对象应该只有typesalarypension
当类型值为3时,对象应该只有typecreditdebit
任何其他的组合都将作为错误从joi验证器中间件层抛出。同样,除了1、2和3之外的任何其他类型值都将抛出错误。

btqmn9zl

btqmn9zl2#

对我有用!

var Joi = require('joi');

var schema = {
    a: Joi.any().when('b', { is: 5, then: Joi.required(), otherwise: Joi.optional() }),
    b: Joi.any()
};

var thing = {
    b: 5
};
var validate = Joi.validate(thing, schema);

// returns
{
    error: null,
    value: {
        b: 5
    }
}

这是参考。

mv1qrgav

mv1qrgav3#

在文档中看起来switch是与alternatives.conditional一起使用的有效密钥。您可以尝试以下操作吗?

const schema = Joi.alternatives().conditional(Joi.object({
  type: 1
}).unknown(), {
  switch: [{
    is: 1,

    then: Joi.object({
      type: Joi.string(),
      firstname: Joi.string(),
      lastname: Joi.string(),
    }),
  }, {
    is: 2,

    then: Joi.object({
      type: Joi.number(),
      salary: Joi.any(),
      pension: Joi.any(),
    }),
  }, {
    // ...
  }],
});
    • 编辑**:

找不到任何关于使用switch关键字的示例...
但是在hapijs/joi github中找到了一些其他的方法来实现它

const schema = Joi.object({
     a: Joi.number().required(),
     b: Joi.alternatives()
             .conditional('a', [
                 { is: 0, then: Joi.valid(1) },
                 { is: 1, then: Joi.valid(2) },
                 { is: 2, then: Joi.valid(3), otherwise: Joi.valid(4) }
    ])
});
41ik7eoe

41ik7eoe4#

我在试着找一种方法来做类似的事情。然后我就能想通了。

const Joi = require('joi');
const schema = Joi.object({
  type: Joi.number().valid(1,2,3),
  // anything common
}).when(Joi.object({type: Joi.number().valid(1)}).unknown(), {
  then: Joi.object({
    firstname: Joi.string(),
    lastname: Joi.string(),
  })
})
.when(Joi.object({type: Joi.number().valid(2)}).unknown(), {
  then: Joi.object({
    salary: Joi.number(),
    pension: Joi.number(),
  })
})
.when(Joi.object({type: Joi.number().valid(3)}).unknown(), {
  then: Joi.object({
    credit: Joi.number(),
    debit: Joi.number(),
  })
});
izj3ouym

izj3ouym5#

我也想做同样的事情,但是条件应该依赖于请求方法,而不是查询参数。

const schema = Joi.when(Joi.ref("$requestMethod"), {
  switch: [
    {
      is: "POST",
      then: Joi.object({
        name: Joi.string().trim().max(150).required(),
        description: Joi.string().max(255),
        active: Joi.boolean().required(),
        }),
      }),
    },
    {
      is: "PUT",
      then: Joi.object({
        name: Joi.string().trim().max(150).required(),
        description: Joi.string().max(255),            
      }),
    },
  ],
});

schema.validate(req.body, { context: { requestMethod: req.method } });

Joi when()条件文档https://joi.dev/api/?v=17.4.1#anywhencondition-options

fdx2calv

fdx2calv6#

使用条件/开关,其语法也更具可读性。
下面的Joi摘录将在$.type === Type.REFERENCE时强制$.referenceClass的存在。当它这样做时,它将确保值是可接受的值-...classIds
否则($.type !== Type.REFERENCE),它将不允许$.referenceClass的存在(除非您运行验证时选择允许额外的密钥)。

{
    type: Joi.string().valid( ...Hub.types ).required(),
    referenceClass: Joi.alternatives().conditional( 'type', {
        switch: [
            { is: Type.REFERENCE, then: Joi.string().valid( ...classIds ) },
        ],
    } ),
}
pepwfjgg

pepwfjgg7#

我认为这个解决方案是可读的,也反映了歧视工会非常好。

const combination1 = Joi.object({
  type: Joi.valid(1),
  firstname: Joi.string(),
  lastname: Joi.string(),
});
const combination2 = Joi.object({
  type: Joi.valid(2),
  salary: Joi.number(),
  pension: Joi.number(),
});
const combination3 = Joi.object({
  type: Joi.valid(3),
  credit: Joi.number(),
  debit: Joi.number(),
});
const schema = Joi.alternatives().try(combination1, combination2, combination3);

相关问题