如何使用Joi,Mongoose&amp ;;验证鉴别器阵列哈皮?

时间:2018-04-20 10:52:20

标签: javascript node.js mongoose joi

我们假设我们的模型设置如下:

const model = new mongoose.Schema({
  foo: {
    type: String,
    required: true,
  },
  discriminatorArray: [new mongoose.Schema({
    bar: {
      type: String,
      required: false,
    }
  }, {
    discriminatorKey: 'baz',
    _id: false,
  })],
});

const docArray = model.path('discriminatorArray');

docArray.discriminator('discriminatorValue1', anotherModel1);
docArray.discriminator('discriminatorValue2', anotherModel2);

mongoose.model('Model', model);

结果是:

{
  "foo": "someValue",
  "discriminatorArray": [{
    "bar": "someValue",
    "baz": "discriminatorValue1",
    "anotherModel1Prop": "someValue"
  }, {
    "bar": "someValue",
    "baz": "discriminatorValue2",
    "anotherModel2Prop": "someValue"
  }]
}

如何使用Joi正确验证数组?

样板:

Joi.validate(payload, Joi.object({
  foo: Joi
    .string()
    .required(),
  discriminatorArray: Joi
    .array()
    .items(Joi.object({
      bar: Joi
        .string()
        .optional(),
      baz: Joi
        .string()
        .valid(['discriminatorValue1', 'discriminatorValue2'])
        .required(),
    }))
    .required(),
}));

我能做到这一点的唯一两种方法是:

  1. 包含anotherModel1&的所有可能密钥。 anotherModel2,然后使用
  2. Joi.when('baz', {
      is: 'discriminatorValue1',
      then: Joi.string(),
      otherwise: Joi.forbidden(),
    })
    

    然而,不同的模型共享一些相同的密钥,这最终会变得混乱,并且包含所有密钥对我来说没有意义,而是为不同的鉴别器创建单独的模式并使用如下内容:

    const items = Joi.object().keys({
      bar: Joi
        .string()
        .optional(),
      baz: Joi
        .string()
        .valid(['discriminatorValue1', 'discriminatorValue2'])
        .required(),
    });
    
    const schema = Joi.object({
      foo: Joi
        .string()
        .required(),
      discriminatorArray: Joi
        .array()
        .items(items.when('baz', {
          is: 'discriminatorValue1',
          then: object.keys(anotherSchema1),
        }).when('baz', {
          is: 'discriminatorValue2',
          then: object.keys(anotherSchema2),
        })),
    });
    
    1. 将模型更改为:
    2. {
        "foo": "someValue",
        "someArray": [{
          "baz": "discriminatorValue1",
          "discriminatorArray": [{
            "anotherModel1Prop": "someValue"
          }]
        }, {
          "baz": "discriminatorValue2",
          "discriminatorArray": [{
            "anotherModel2Prop": "someValue"
          }]
        }]
      }
      

      因此Joi验证看起来像这样(未经测试):

      Joi.validate(payload, Joi.object({
        foo: Joi
          .string()
          .required(),
        someArray: Joi
          .array()
          .items(Joi.object({
            baz: Joi
              .string()
              .valid(['discriminatorValue1', 'discriminatorValue2'])
              .required(),
            discriminatorArray: Joi
              .array()
              .when('baz', {
                is: 'discriminatorValue1',
                then: Joi
                  .array()
                  .items(Joi.object({
                    anotherModel1Prop: Joi
                      .string()
                      .required(),
                  })),
              })
              .when('baz', {
                is: 'discriminatorValue2',
                then: Joi
                  .array()
                  .items(Joi.object({
                    anotherModel2Prop: Joi
                      .string()
                      .required(),
                  })),
              }),
          }))
          .required(),
      }));
      

      对此的任何想法和解决方案都会很棒。

      资源:

1 个答案:

答案 0 :(得分:0)

我决定包括所有可能的密钥并编写一些逻辑来构建基于配置文件的模式。

配置数组如下所示:

{
  key: 'anotherModel1Key',
  required: true,
}

然后我写了这样的话:

const items = {
  bar: Joi
    .string()
    .optional(),
  baz: Joi
    .string()
    .valid(['discriminatorValue1', 'discriminatorValue2'])
    .required(),
};

// function to add additional keys from configs which ends with

items[key] = Joi.when('baz', {
  is: Joi.only(arrayOfBazValuesIdentifyingWhenThisKeyIsAllowed),
  then: Joi.string().trim()[required](),
  otherwise: Joi.forbidden(),
});

然后返回架构:

return Joi.validate(payload, Joi.object({
  foo: Joi
    .string()
    .required(),
  discriminatorArray: Joi
    .array()
    .items(items)
    .required(),
}));