标记所有属性是否为必需的Joi [英] Mark all properties as required or not Joi

查看:58
本文介绍了标记所有属性是否为必需的Joi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建Express API,并使用@ hapi/joi进行验证.但是,我发现自己处于以下情况:如果要验证新用户,则必须要求架构中的所有属性,但是如果客户端要修改用户,则这些属性必须是可选的,因为只有客户端知道什么它将修改的属性.因此,如果我有新用户使用此架构:

I'm building an Express API and using @hapi/joi for validation. However I find myself in the following situation: if I want to validate a new user, all the properties in the schema have to be required, but if the client wants to modify a user, these properties must be optional since only the client knows what properties it will modify. So if I have this schema for new users :

function validateUser(user) {
  const schema = Joi.object().keys({
    name: Joi.string().required(),
    lastName: Joi.string().required(),
    email: Joi.string().email().required(),
    password: Joi.string().required(),
    address: Joi.string().required(),
    city: Joi.string().required(),
    district: Joi.string().required()
});

  return schema.validate(user);
}

由于所有属性都是必需的,因此当我想使用具有相同属性但都是可选属性的架构时,我必须对所有属性都是可选属性的另一个架构进行硬编码.有没有办法避免Joi的冗余代码?就像传递给validateUser函数的isNew参数将其应用于架构一样?

Since all the properties are required, when I want to use a schema with the same properties but all optional, I have to hard code another schema where all properties are optional. Is there a way or an option of Joi to avoid redundant code? Like an isNew parameter passed to the validateUser function to apply it to the schema?

推荐答案

我想您以错误的方式解决了该问题.模式通常应描述您的类型在数据库中的状态.例如,如果需要名字,那么创建或更新名字时总是会无意中使用它.因此,在进行更新的情况下,您将从db获取该项目并在其之上应用更改,然后将其发送以进行验证.

I guess you are tackling the problem in a wrong way. Schema should generally depict how your types are in DB. for example if a first name is required, it will always be required irresepective if it is create or update. So in case of update you will fetch the item from db and apply changes on top of that and then send it for validation.

如果您确实想这样做,可以将上下文传递给validate函数,可以使用 $ 符号从joi模式中访问该函数.您在这里有两个选择,或者对每个属性应用其他条件,这将使您的架构看起来丑陋,或者全部具有两个版本的架构,并根据传递的上下文的值进行选择.像这样

If you really want to do it this way, you could pass context to your validate function which can be accessed from your joi schema using $ sign. You have two choices here, either apply if else condition for each property which will make your schema look ugly OR have all togather two version of schema and choose depending upon value of the context passed. Something like this

const Joi = require("@hapi/joi");

const schemaA = Joi.object().keys({
  "name": Joi.string().required(),
  "lastName": Joi.string().required(),
  "email": Joi.string().email().required(),
  "password": Joi.string().required(),
  "address": Joi.string().required(),
  "city": Joi.string().required(),
  "district": Joi.string().required()
});

const schemaB = Joi.object().keys({
  "name": Joi.string(),
  "lastName": Joi.string(),
  "email": Joi.string().email(),
  "password": Joi.string(),
  "address": Joi.string(),
  "city": Joi.string(),
  "district": Joi.string()
});

function ChooseSchema() {
  return Joi.when(Joi.ref("$isNew"), {
    "is": true,
    "then": schemaA,
    "otherwise": schemaB
  });
}

console.log(ChooseSchema().validate({"name": "ashish"}, {"context": {"isNew": true}}));
console.log(ChooseSchema().validate({"name": "ashish"}, {"context": {"isNew": false}}));


这篇关于标记所有属性是否为必需的Joi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆