Joi: Adding rules to a new Joi.object clone does not work as expected

Created on 5 Aug 2016  路  10Comments  路  Source: sideway/joi

Context

  • _node version_: 6.2.2
  • _joi version_: 8.4.2
  • _environment_: node

I'd like to describe one core model with all data type validation and extend that model in multiple places with different key require/optional values.

'use strict';

const Joi = require('joi');
var Person = Joi.object({
  name: Joi.string(),
  height: Joi.number(),
  favoriteMovies: Joi.array()
});

var MovieLover = Person.keys({
  favoriteMovies: Joi.required()
});

var MeasuredPerson = Person.keys({
  height: Joi.required()
});

Expected Result

MovieLover.describe() response:

{ type: 'object',
  children: 
   { name: { type: 'string', invalids: [ '' ] },
     height: { type: 'number', invalids: [ Infinity, -Infinity ] },
     favoriteMovies: { type: 'array', flags: { sparse: false, presence: 'required' } } } }

Actual Result

{ type: 'object',
  children: 
   { name: { type: 'string', invalids: [ '' ] },
     height: { type: 'number', invalids: [ Infinity, -Infinity ] },
     favoriteMovies: { type: 'any', flags: { presence: 'required' } } } }

If this is not possible, is there another way to achieve this behavior? The modifications I would like to make are purely require/optional based. So exporting, add the presence: 'required' flag, and re-importing would be an option.

Furthermore, if that too is not possible and could be added as an enhancement how would that be structured? I am willing to make this contribution to the project myself.

support

Most helpful comment

The documentation doesn't make this (amazing) feature entirely clear. Including the end result should a future reader come across this:

'use strict';

const Joi = require('joi');
var Person = Joi.object({
  name: Joi.string(),
  height: Joi.number(),
  favoriteMovies: Joi.array()
});

var MovieLover = Person.concat(Joi.object({
  favoriteMovies: Joi.required()
}));

var MeasuredPerson = Person.concat(Joi.object({
  height: Joi.required()
}));

All 10 comments

You might look into usage of Joi.any().concat() https://github.com/hapijs/joi/blob/master/API.md#anyconcatschema

Correct answer @devinivy, keys replaces, concat merges.

The documentation doesn't make this (amazing) feature entirely clear. Including the end result should a future reader come across this:

'use strict';

const Joi = require('joi');
var Person = Joi.object({
  name: Joi.string(),
  height: Joi.number(),
  favoriteMovies: Joi.array()
});

var MovieLover = Person.concat(Joi.object({
  favoriteMovies: Joi.required()
}));

var MeasuredPerson = Person.concat(Joi.object({
  height: Joi.required()
}));

Yeah, I had no clue about that feature either. It's definitely documented in a succinct and easy to understand way right now here though.

Just one other question that isn't entirely related to this issue but also can't find an answer to. Is there a way to set other keys to unknown on a concat'd schema?

i.e.

var MeasuredPerson = Person.concat(Joi.object({
  height: Joi.required()
})).unknown(false);

which would inherit the validation info for height AND prevent keys other than height.

Don't try to think object-oriented, you're building validation schemas, you don't need to always use Person.

@Marsup the issue is we had been doing things like that but we ended up with far too many files to keep track of and duplicated data was not always being updated properly.

Are those in separate files ? A little context might help me provide a better answer :)

Yes. We have separate files for each response schema at the moment. For now we're going to use the following which works fine.

var MeasuredPerson = Person.concat(Joi.object({
  height: Joi.required(),
  favoriteMovies: Joi.forbidden(),
  name: Joi.forbidden()
}));

Then you might extract what you need from this, but at some point you'll find it easier to just export the interesting parts from your Person schema :

var MeasuredPerson = Joi.object({
  height: Joi.reach(Person, 'height').required()
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

normancarcamo picture normancarcamo  路  3Comments

kailashyogeshwar85 picture kailashyogeshwar85  路  4Comments

a-c-m picture a-c-m  路  3Comments

PaunPrashant picture PaunPrashant  路  3Comments

REBELinBLUE picture REBELinBLUE  路  3Comments