好吧,我放弃...

如何使selectorSettings仅在selectorStrategy设置为tournament时出现?

selectorStrategy: joi.string().valid(['tournament',  'roulette']).default('tournament'),
selectorSettings: joi.any().when('selectorStrategy', {
  is: 'tournament',
  then: joi.object().keys({
     tournamentSize: joi.number().integer().default(2),
     baseWeight: joi.number().integer().default(1)
   })
 })


我在选项中设置了stripUnknown: true。我的期望是,如果我通过:

 selectorStrategy: 'roulette',
 selectorSettings: { tournamentSize: 3 }


我会得到:

selectorStrategy: 'roulette'


如果我这样做:

selectorStrategy: 'tournament'


我会得到:

 selectorStrategy: 'tournament',
 selectorSettings: { tournamentSize: 2, baseWeight: 1 }

最佳答案

您需要设置一个selectorSettings默认值,并根据selectorStrategy的值有条件地将其删除。

让我们看一下您的两个用例。

根据同级值删除密钥

const thing = {
  selectorStrategy: 'roulette',
  selectorSettings: { tournamentSize: 3 },
};

joi.validate(thing, schema, { stripUnknown: true} );


selectorSettings不会被stripUnknown选项删除,因为密钥不是未知的-它在您的模式中。

我们需要根据selectorStrategy的值将其显式删除:

.when('selectorStrategy', {
  is: 'tournament',
  otherwise: joi.strip(),
}),


根据同级值添加/验证密钥

const thing = {
  selectorStrategy: 'tournament'
};

joi.validate(thing, schema);


该代码未设置selectorSettings键本身的默认值,仅设置了其属性。由于不需要selectorSettings,因此验证通过。

我们需要设置一个默认值:

selectorSettings: joi
  .object()
  .default({ tournamentSize: 2, baseWeight: 1 })




处理这两种情况的修改后的代码如下所示:

const joi = require('joi');

const schema = {
  selectorStrategy: joi
    .string()
    .valid(['tournament', 'roulette'])
    .default('tournament'),
  selectorSettings: joi
    .object()
    .default({ tournamentSize: 2, baseWeight: 1 })
    .keys({
      tournamentSize: joi
        .number()
        .integer()
        .default(2),
      baseWeight: joi
        .number()
        .integer()
        .default(1),
    })
    .when('selectorStrategy', {
      is: 'tournament',
      otherwise: joi.strip(),
    }),
};


例子

// should remove settings when not a tournament
var thing = {
  selectorStrategy: 'roulette',
  selectorSettings: { tournamentSize: 3 },
};

// returns
{
  "selectorStrategy": "roulette"
}




// should insert default settings
var thing = {
  selectorStrategy: 'tournament'
};

// returns
{
  "selectorStrategy": "tournament",
  "selectorSettings": {
    "tournamentSize": 2,
    "baseWeight": 1
  }
}




// should add missing baseWeight default
var thing = {
  selectorStrategy: 'tournament',
  selectorSettings: { tournamentSize: 5 }
};

// returns
{
  "selectorStrategy": "tournament",
  "selectorSettings": {
    "tournamentSize": 5,
    "baseWeight": 1
  }
}

07-24 16:44