Joi: string that contains only numbers

Created on 12 Apr 2017  Â·  17Comments  Â·  Source: sideway/joi

More like a question than an issue. Going through documentation i don't see how i can validate that string only contains numbers in another words im trying to validate string where valid value should be only positive number like "1234". Invalid value would be "0" or "-1". I know i can use something like Joi.number().positive().integer(), but i want strict validation in which "1"(string) is valid and 1(integer) is not valid

support

Most helpful comment

Don't think many people want that, plus Joi.string().regex(/^\d+$/) is about as effective as this.

All 17 comments

Use a regex for that.

@Marsup wouldn't be nice to have something like, Joi.string().numeric().positive()

Don't think many people want that, plus Joi.string().regex(/^\d+$/) is about as effective as this.

@Marsup Effective but not user friendly that much, many validator libs has something similar. For example https://www.npmjs.com/package/validator .isNumeric

Anyway thank you on response, closing this one

Different libs, different ways of doing things. This one only deals with strings it seems, so I would certainly hope it supports it. People who want numbers usually use joi.number().

Well we could argue on this without concrete conclusion. In my opinion whatever API should be strict as hell. If my API is expecting to see string "1" and not integer 1 although it could complete its task if it receives integer i would throw validation error cause API should expose contract to its clients how they should invoke it. Client should not choose to send whatever he like

You can always extend joi's api if you feel some primitives are missing, but a string could basically represent everything, and I don't intend to bring all the other types checking into the string api.

Anyone have an idea why this doesn't work?

const schema = Joi.when('', {
    is: Joi.number().min(0),
    then: Joi.string(),
    otherwise: Joi.valid()
});

schema.validate(123);    // Should go to "then" and fail– not a string.  Works!
schema.validate('123');  // Should go to "then" and succeed.  Works!
schema.validate('-123'); // Should go to "otherwise" and fail.  But it doesn't?

@devinivy The reason why is because Joi utilizes type coercion as well, so that number 123 is being coerced into "123" instead and it is valid. Similarly this is occuring when you are sending "123" as it is being coerced into a Number to pass the is check.

See the validate() function options, specifically the convert parameter. This can also be selectively applied with the strict() flag.

@devinivy You thought it worked, it didn't. A reference to '' points to nothing, this gives undefined, Joi.number().min(0) is not required, so undefined is valid, the then is applied and fails. Same goes for each and every case you gave, it will always pick the then.

I think the main use case I can think of for a Joi.string().numeric() is cases where it should remain a string and keep padding zeros intact.

for example 082000549 is a routing number and It would be wrong if it ended up as 82000549

I don't see this as dramatically different from alphanum

@CharlieEarnup you can do that with Joi.number().raw(). The problem with this request is that everyone wants something different, and at the end, it is often to validate a number but keep the string. Sometimes with the tailing zeros, sometimes without. Between raw() and cast() you can accomplish a more expressive and accurate schema.

Okay good to know I can use that.

However it still seems to me to be inconsistent with the established grammar of the api which tends towards Joi.<ValidateType>.<ValidateContent>.... Since you couldn't precisely represent certain numeric strings as a number type, It does throw the user through a loop.

For that reason semantically I still think Joi.string().numeric() is more clear than Joi.number().integer().raw().

If there was a real need for this, sure. But everything has a cost, especially now with browser support size matters.

Don't think many people want that, plus Joi.string().regex(/^\d+$/) is about as effective as this.

thank you for this

I want a numeric string of at least 20 digits.

Joi.string().numeric().min(20)

> Joi.number().integer().raw().validate("01234567890123456789")
{
  value: '01234567890123456789',
  error: [Error [ValidationError]: "value" must be a safe number] {
    isJoi: true,
    name: 'ValidationError',
    _original: '01234567890123456789',
    details: [ [Object] ]
  }
}

Using number().integer().raw() isn't expressive at all, it just doesn't match my intention, and it... doesn't work.

Using a regular expression is stupid. Why have alphanum but not numeric? If I cared about browser package size and liked non-expressive code and/or regular expressions, I would just... use regular expressions without a library at all.

@tobyhinloopen

Using a regular expression is stupid.

So is thinking you can get support with this attitude. I suggest you find a different solution that is less stupid.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

normancarcamo picture normancarcamo  Â·  3Comments

n-sviridenko picture n-sviridenko  Â·  3Comments

kevbook picture kevbook  Â·  4Comments

a-c-m picture a-c-m  Â·  3Comments

REBELinBLUE picture REBELinBLUE  Â·  3Comments