Skip to content

Validating unique optional fields in array elements. #1498

@BryceCicada

Description

@BryceCicada

Context

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

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

let Joi = require('joi');

const objSchema = Joi.object({
   foo: Joi.string().optional()
});

const arrSchema = Joi.array().items(objSchema).unique('foo');

let validationResult = arrSchema.validate([{}, {}]);

if (!validationResult.error) {
    console.log('OK!');
} else {
    let detail = validationResult.error.details[0];
    if (detail.type === 'array.unique') {
        // Create a user-friendly custom error message
        let context = detail.context;
        console.error(`Duplicate element ${context.path} for objects at indices ${context.pos} and ${context.dupePos}`);
    } else {
        // Just log the Joi error
        console.error(detail.message);
    }
}

Which result you had ?

output was:

Duplicate element foo for objects at indices 1 and 0

That is, I got a validation error because the two objects were missing the optional string element 'foo'. I understand that Joi has interpreted this as if I was validating [{foo:undefined}, {foo:undefined}], for which clearly the value of foo is not unique among the array elements. This is documented behaviour.

What did you expect ?

  1. I'd like to not fail the validation when these optional fields are undefined... ie only check uniqueness among the defined fields 'foo'.
  2. Additonally, I'd like to construct a custom error message by using the error detail context path.

I can acheive 1 by doing:

const arrSchema = Joi.array().items(objSchema).unique((a,b) => a.foo && b.foo && a.foo === b.foo);

but then there's no path element defined for me to construct an error message with.

I wonder if something like the following makes sense:

  • allow an additional param to unique('foo') to compare only defined values. Or,
  • allow an additional param to unique((a,b) => a.foo && b.foo && a.foo === b.foo) to provide the path in the error.

Any thoughts?

Thank you.

Metadata

Metadata

Assignees

Labels

featureNew functionality or improvement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions