Joi: Way to display errors for specific item in array of items

Created on 21 Apr 2017  路  6Comments  路  Source: sideway/joi

Context

  • node version: any
  • joi version: any
  • environment (node, browser): node
  • used with (hapi, standalone, ...): standalone
  • any other relevant information:

What are you trying to achieve or the steps to reproduce ?

When my array schema includes more than one possible value, error message will be quite general and there is no way to make it more accurate.

example code:

const Joi = require('joi');

const schema = Joi.array()
    .items(Joi.object({
        type: 'text',
        messages: Joi.array().items(Joi.string().max(2048)).min(1).max(30).required()
    }))
    .items(Joi.object({
        type: 'image',
        imageUrl: Joi.string().uri().required()
    }));

const value = {
    type: 'text',
    messages: []
};

console.log(Joi.validate([value], schema));

Which result you had ?

Error: "value" at position 0 does not match any of the allowed types

What did you expect ?

Error: "value" at position 0 fails because [child "messages" fails because ["messages" must contain at least 1 items]]

feature

Most helpful comment

With this feature: https://github.com/hapijs/joi/issues/1325 this issue can be closed. To more accurate error messages, just simply use when extensively.

For example:

const Joi = require('joi');


const fooType = Joi.object()
    .keys({
        type: 'foo',
        foo: Joi.string().valid('foo')
    });

const barType = Joi.object()
    .keys({
        type: 'bar',
        bar: Joi.string().valid('bar')
    });

const item = Joi.object()
    .when(Joi.object({ type: 'foo' }).unknown(), { then: fooType })
    .when(Joi.object({ type: 'bar' }).unknown(), { then: barType });

const schema = Joi.array().items(item);

const value = {
    type: 'foo',
    bar: 'bar'
};

schema.validate([value], err => console.log(err && err.message));

will result in:

Error: "value" at position 0 fails because ["bar" is not allowed]

Thanks @Marsup !

All 6 comments

Happy to take a PR if you ever manage to find a strategy to determine which is the better choice between all provided schemas.

With this feature: https://github.com/hapijs/joi/issues/1325 this issue can be closed. To more accurate error messages, just simply use when extensively.

For example:

const Joi = require('joi');


const fooType = Joi.object()
    .keys({
        type: 'foo',
        foo: Joi.string().valid('foo')
    });

const barType = Joi.object()
    .keys({
        type: 'bar',
        bar: Joi.string().valid('bar')
    });

const item = Joi.object()
    .when(Joi.object({ type: 'foo' }).unknown(), { then: fooType })
    .when(Joi.object({ type: 'bar' }).unknown(), { then: barType });

const schema = Joi.array().items(item);

const value = {
    type: 'foo',
    bar: 'bar'
};

schema.validate([value], err => console.log(err && err.message));

will result in:

Error: "value" at position 0 fails because ["bar" is not allowed]

Thanks @Marsup !

Cool, thanks for letting me know.

const Joi = require('joi');

const fooType = Joi.object().keys({
  type: 'foo',
  foo: Joi.string().valid('foo')
});

const barType = Joi.object().keys({
  type: 'bar',
  bar: Joi.string().valid('bar')
});

const item = Joi.object()
  .when(Joi.object({ type: 'foo' }).unknown(), { then: fooType })
  .when(Joi.object({ type: 'bar' }).unknown(), { then: barType });

const schema = Joi.array().items(item);

schema.validate([{ type: 'bad type' }], (err) => console.log(err && err.message));

The code approve will not fail, as long as enter a type not defined in the item schema.
Is there simple way to guard against that ?

I found a solution perhaps not so pretty but it works

const item = Joi.object({ type: Joi.string().valid('foo', 'bar') })
  .when(Joi.object({ type: 'foo' }).unknown(), { then: fooType })
  .when(Joi.object({ type: 'bar' }).unknown(), { then: barType });

@kaareal your solution is the way I'm doing it too, just get used to it ;)

That's because Joi.object({ type: 'foo' }) is strictly equivalent to Joi.object({ type: Joi.only('foo') }), notice how type is not required.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mohamadresaaa picture mohamadresaaa  路  3Comments

REBELinBLUE picture REBELinBLUE  路  3Comments

leore picture leore  路  4Comments

alekbarszczewski picture alekbarszczewski  路  3Comments

jamesdixon picture jamesdixon  路  4Comments