簡體   English   中英

Joi 驗證 - 如何根據數組中存在的另一個鍵來要求或可選字段?

[英]Joi validation - how to require or optional field based on another key exists in array?

我有這個 Joi 架構:

  let schema = {};

  let stations = {
    contact: {
      first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
    },
    address: {
      place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').required().error(JoiCustomErrors),
      city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
      street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
      house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
    },
    passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
    notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
  };
  schema.stations = Joi.array().items(stations).min(1).max(5).required().error(JoiCustomErrors);

如您所見, schema.stations是一個包含最少 1 和最多 5 個元素的數組。 我希望每個元素只有在"contact.first_name" AND "contact.last_name" AND "contact.phone"存在(或根據架構正確填充)時才具有“address.place”字段。

我怎樣才能做到這一點?

您可以使用Joi.when()方法並創建這樣的架構:

Joi.object().keys({
    contact: Joi.object().keys({
        first_name: Joi.string(),
        last_name: Joi.string(),
        phone: Joi.string(),
    }),
    address: Joi.object().keys({
        place: Joi.string(),
        city: Joi.string().min(2).max(30),
        street: Joi.string(),
        house_number: Joi.string()
    }).when('contact', {
        is: Joi.object().keys({
            first_name: Joi.exist(),
            last_name: Joi.exist(),
            phone: Joi.exist(),
        }),
        then: Joi.object({ place: Joi.required() }).required(),
        otherwise: Joi.object({ place: Joi.forbidden() })
    }),
    passengers_amount: Joi.number(),
    notes: Joi.string()
});

我只是簡化了你的shema,所以很容易理解。

基本上,我們在這里說的是,如果contact.first_namecontact.last_namecontact.phone存在,那么addressaddress.place必需的,否則address.place禁止

例如,這個對象將失敗,因為地址不存在:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    }
}

這將失敗,因為address.place不存在:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    },
    contact: {
    }
}

最后,根據定義的模式,這個對象將通過:

{
    address: {
        first_name: 'a',
        last_name: 'b',
        phone: 'c'
    },
    contact: {
        place: 'd'
    }
};

感謝 Soltex,這是應該使用的正確模式(但請參考我所做的更改):

Joi.object().keys({
    contact: {
      first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
      phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
    },
    address: Joi.object().keys({
      place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').error(JoiCustomErrors),
      city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
      street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
      house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
    }).when('contact', {
      is: Joi.object().keys({
        first_name: Joi.string().min(1),
        last_name: Joi.string().min(1),
        phone: Joi.string().min(1),
      }),
      then: Joi.object({ place: Joi.required() }).required(),
      otherwise: Joi.object({
        place: Joi.optional().allow("")
      })
    }),
    passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
    notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
  })

請注意,我對 Soltex 的回答的回答發生了變化:他將 when "contact.first_name" "contact.last_name" "contact.phone"改為: Joi.exists() 這不好,因為以這種方式,即使是空對象也是“存在”的,然后要求用戶提供“address.place”。 我們不想要這樣的東西,我們需要在每個字段中至少有一個字符。

另外,Soltex 答案中的其他聲明是使用Joi.forbidden()而這不是此處所需的行為 - 我們仍然需要允許用戶提供位置,即使沒有聯系,但這不應該是強制性的 -所以我使用了: Joi.optional()代替。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM