Joi 在架构定义中嵌套“when”条件失败,出现“ERR_ASSERTION”错误

Joi nested `when` conditions failed in schema definition with `ERR_ASSERTION ` error

我一直在尝试使用 Joi(旧版本 14.3.1)来创建模式,不幸的是,我被卡住了。我尝试了多种方法来定义模式,但结果总是在模式定义中出现错误。

这是我的架构定义:

 const allowedUser = {
    admin: 'ADMIN',
    normal: 'NORMAL'
  };

  const schema = validator
    .object()
    .keys({
      user: validator.any().valid(Object.values(allowedUser)).required(),
      context: validator.object().default({})
    })
    .when('user', {
      is: allowedUser.admin,
      then: validator.when(validator.object({ context: validator.exist() }), {
        then: validator.object().keys({
          session: validator.string().required()
        })
      })
    })
    .when('user', {
      is: allowedUser.normal,
      then: validator.when(validator.object({ context: validator.exist() }), {
        then: validator.object().keys({
          id: validator.string().required()
        })
      })
    });

我尝试的另一个模式定义:

  const schema = validator.object().keys({
    user: validator.any().valid(Object.values(allowedUser)).required(),
    context: validator
      .object()
      .when('user', {
        is: allowedUser.admin,
        then: validator.when('context', {
          is: validator.exist(),
          then: validator.object().keys({
            session: validator.string().required()
          })
        })
      })
      .when('user', {
        is: allowedUser.normal,
        then: validator.when('context', {
          is: validator.exist(),
          then: validator.object().keys({
            id: validator.string().required()
          })
        })
      })
      .default({})
  });

所以schema的条件如下:

  1. user 的情况下键入 ADMIN:如果定义了 context 属性,它应该包含 属性 session。如果 context 属性 未定义,则应将默认值设置为 {}
  2. user 类型 NORMAL 的情况下:如果定义了 context 属性,它应该包含 属性 id。如果 context 属性 未定义,则应将值默认设置为 {}
  3. 隐式情况是如果 context 属性 包含未知 属性 它也应该失败

当我 运行 代码时,我总是在模式定义中遇到错误,如下所示:

AssertionError [ERR_ASSERTION]: Cannot merge type object with another type: alternatives
    

我的最小示例代码如下:

const validator = require('joi');


  const allowedUser = {
    admin: 'ADMIN',
    normal: 'NORMAL'
  };

  const bodyWhenUndefined = {
    user: 'ADMIN',
    message: 'Hi'
  };

  const bodyWhenValidDefined = {
    user: 'ADMIN',
    message: 'Hi'
  };


  const bodyWhenDefinedEmpty = {
    user: 'ADMIN',
    message: 'Hi 2',
    context: {}
  };

  const bodyWhenDefinedWrong = {
    user: 'admin',
    message: 'Hi 3',
    context: {abc: 'wrong property'}
  };

  const schema = validator
    .object()
    .keys({
      user: validator.any().valid(Object.values(allowedUser)).required(),
      context: validator.object().default({})
    })
    .when('user', {
      is: allowedUser.admin,
      then: validator.when(validator.object({ context: validator.exist() }), {
        then: validator.object().keys({
          session: validator.string().required()
        })
      })
    })
    .when('user', {
      is: allowedUser.normal,
      then: validator.when(validator.object({ context: validator.exist() }), {
        then: validator.object().keys({
          id: validator.string().required()
        })
      })
    });


   const resultSuccess = validator.validate(bodyWhenValidDefined, schema);
    console.log("This is with success in validation",resultSuccess.value);

    const result = validator.validate(bodyWhenUndefined, schema);
    console.log("This is with default context property",result.value);


    const resultWithEmptyError = validator.validate(bodyWhenDefinedEmpty, schema);
    console.log("This should come with error with required property session",resultWithEmptyError.error);

    const resultWithWrongProp = validator.validate(bodyWhenDefinedWrong, schema);
    console.log("This should come with error with required property session",resultWithWrongProp.error);


我已经创建了一个有效的 REPL fiddle here 如果您能告诉我哪里做错了,我们将不胜感激。

多亏了找到的 REPL here。我了解了如何根据同级 属性 值定义嵌套模式。您可以简单地为对象提供 then 条件并定义所需的属性。这是工作模式:

  const schema = validator.object().keys({
    user: validator.any().valid(Object.values(allowedUser)).required(),
    message: validator.string(),
    context: validator
      .object()
      .when('user', {
        is: allowedUser.admin,
        then: {
          session: validator.required()
        }
      })
      .when('user', {
        is: allowedUser.normal,
        then: {
          id: validator.required()
        }
      })
      .default({})
  });