简体   繁体   中英

Add conditional Joi schema

Ok I give up...

How do I make the selectorSettings only appear when selectorStrategy is set to 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)
   })
 })

I have stripUnknown: true set in my options. My expectations are that if I pass:

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

I will get:

selectorStrategy: 'roulette'

And If I do:

selectorStrategy: 'tournament'

I will get:

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

You need to set a selectorSettings default, and conditionally strip it out based on the value of selectorStrategy .

Let's walk through your two use cases.

Removing a key based on sibling value

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

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

selectorSettings won't be removed by the stripUnknown option, because the key is not unknown - it's in your schema.

We need to explicitly strip it out based on the value of selectorStrategy :

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

Adding / validating keys based on sibling value

const thing = { 
  selectorStrategy: 'tournament'
};

joi.validate(thing, schema);

The code is not setting a default for the selectorSettings key itself, only its properties. Since selectorSettings is not required, the validation passes.

We need to set a default:

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

Modified code that handles both cases would look like this:

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(),
    }),
};

Examples

// 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
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM