How to add custom validator function in Joi?

24,989

Solution 1

Your custom method must be like this:

const method = (value, helpers) => {
  // for example if the username value is (something) then it will throw an error with flowing message but it throws an error inside (value) object without error message. It should throw error inside the (error) object with a proper error message

  if (value === "something") {
    return helpers.error("any.invalid");
  }

  // Return the value unchanged
  return value;
};

Docs:

https://github.com/hapijs/joi/blob/master/API.md#anycustommethod-description

Output for value :

{ username: 'something' }

Output for error:

[Error [ValidationError]: "username" contains an invalid value] {
  _original: { username: 'something' },
  details: [
    {
      message: '"username" contains an invalid value',
      path: [Array],
      type: 'any.invalid',
      context: [Object]
    }
  ]
}

Solution 2

const Joi = require('@hapi/joi');

Joi.object({
    password: Joi
        .string()
        .custom((value, helper) => {

            if (value.length < 8) {
                return helper.message("Password must be at least 8 characters long")

            } else {
                return true
            }

        })

}).validate({
    password: '1234'
});
Share:
24,989
Shifut Hossain
Author by

Shifut Hossain

Updated on October 07, 2020

Comments

  • Shifut Hossain
    Shifut Hossain over 3 years

    I have Joi schema and want to add a custom validator for validating data which isn't possible with default Joi validators.

    Currently, I'm using the version 16.1.7 of Joi

       const method = (value, helpers) => {
          // for example if the username value is (something) then it will throw an error with flowing message but it throws an error inside (value) object without error message. It should throw error inside the (error) object with a proper error message
    
          if (value === "something") {
            return new Error("something is not allowed as username");
          }
    
          // Return the value unchanged
          return value;
        };
    
        const createProfileSchema = Joi.object().keys({
          username: Joi.string()
            .required()
            .trim()
            .empty()
            .min(5)
            .max(20)
            .lowercase()
            .custom(method, "custom validation")
        });
    
        const { error,value } = createProfileSchema.validate({ username: "something" });
    
        console.log(value); // returns {username: Error}
        console.log(error); // returns undefined
    

    But I couldn't implement it the right way. I read Joi documents but it seems a little bit confusing to me. Can anyone help me to figure it out?

  • SuleymanSah
    SuleymanSah over 4 years
    @ShifutHossain I tried it and it gives the error [ValidationError]: "username" contains an invalid value]
  • Shifut Hossain
    Shifut Hossain over 4 years
  • SuleymanSah
    SuleymanSah over 4 years
    Did you try on your local computer?
  • SuleymanSah
    SuleymanSah over 4 years
    @ShifutHossain as I know joi is not compatible in browser, can you check in your node application?
  • SuleymanSah
    SuleymanSah over 4 years
    I added the output in to the answer, when used in a node app. Isn't it what you want?
  • Shifut Hossain
    Shifut Hossain over 4 years
    Yeah, now it's working on node environment. It was my mistake I always use Codesandbox for practicing.
  • SuleymanSah
    SuleymanSah over 4 years
    In codesandbox there is template project for node apps, but I didn't tried.
  • Hoppeduppeanut
    Hoppeduppeanut over 3 years
    While this might answer the question, if possible you should edit your answer to include an explanation of how this code block answers the question. This helps to provide context and makes your answer much more useful to future readers.
  • deb
    deb almost 3 years
    Hmm, types say the 1st arg of helper.message needs to be Record<string, string>, not string...
  • Igorsvee
    Igorsvee almost 3 years
    You can ignore the type error... but I think it should return value instead of true at the end
  • Peter Moses
    Peter Moses over 2 years
    To fix type issue return helper.message({custom: 'put error message here'})
  • Slava Fomin II
    Slava Fomin II over 2 years
    Thanks, but how do you define a custom error text?
  • Slava Fomin II
    Slava Fomin II over 2 years
    First argument of the message() is LanguageMessages which is Record<string, string>.
  • Overclocked Skid
    Overclocked Skid about 2 years
    You don't really need an else statement if you are returning in the if clause, though I recommend commenting and // else to improve readability
  • alex
    alex almost 2 years
    you could validate currentLocation as an array of numbers